Skip to content

Instantly share code, notes, and snippets.

@schaloner
Created December 17, 2015 12:10
Show Gist options
  • Save schaloner/bade0da9033eb04f306f to your computer and use it in GitHub Desktop.
Save schaloner/bade0da9033eb04f306f to your computer and use it in GitHub Desktop.
Auth0 Play Java callback - basic implementation
package be.objectify.example.controllers;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import be.objectify.example.models.User;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.inject.Inject;
import play.cache.CacheApi;
import play.libs.F;
import play.libs.Json;
import play.libs.concurrent.HttpExecutionContext;
import play.libs.ws.WS;
import play.libs.ws.WSResponse;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Result;
public class AuthCallback extends Controller {
private static final String DOMAIN = "example.eu.auth0.com";
private final HttpExecutionContext ec;
private final CacheApi cache;
@Inject
public AuthCallback(final HttpExecutionContext ec,
final CacheApi cache) {
this.ec = ec;
this.cache = cache;
}
public CompletionStage<Result> callback(final Optional<String> maybeCode,
final Optional<String> maybeState) {
return maybeCode.map(code -> getToken(code).thenComposeAsync(tuple -> getUser(tuple._2,
tuple),
ec.current())
.thenApplyAsync(tuple2 -> {
cache.set(tuple2._2._1 + "profile",
tuple2._1);
session("idToken",
tuple2._2._1);
session("accessToken",
tuple2._2._2);
return redirect(routes.Application.dashboard());
},
ec.current())
.exceptionally(t -> unauthorized(t.getMessage())))
.orElseGet(() -> CompletableFuture.supplyAsync(() -> badRequest("No parameters supplied"),
ec.current()));
}
private CompletionStage<F.Tuple<String, String>> getToken(final String code) {
final ObjectNode root = Json.newObject();
root.put("client_id",
"foo");
root.put("client_secret",
"bar");
root.put("redirect_uri",
"http://localhost:9001/callback");
root.put("code",
code);
root.put("grant_type",
"authorization_code");
return WS.url(String.format("https://%s/oauth/token",
DOMAIN))
.setHeader(Http.HeaderNames.ACCEPT,
Http.MimeTypes.JSON)
.post(root)
.thenApplyAsync(WSResponse::asJson,
ec.current())
.thenApplyAsync(json -> new F.Tuple<>(json.get("id_token").asText(),
json.get("access_token").asText()),
ec.current())
.exceptionally(t -> {
throw new IllegalStateException("Tokens not sent");
});
}
private CompletionStage<F.Tuple<User, F.Tuple<String, String>>> getUser(final String accessToken,
final F.Tuple<String, String> tuple) {
return WS.url(String.format("https://%s/userinfo",
DOMAIN))
.setQueryParameter("access_token",
accessToken)
.get()
.thenApplyAsync(WSResponse::asJson,
ec.current())
.thenApplyAsync(json -> new F.Tuple<>(new User.Builder().givenName(json.get("name").asText()).build(),
tuple),
ec.current());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment