package io.vertx.ext.auth.oauth2.providers;

import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.oauth2.OAuth2Auth;
import io.vertx.ext.auth.oauth2.OAuth2ClientOptions;
import io.vertx.ext.auth.oauth2.OAuth2Response;

import static io.vertx.ext.auth.oauth2.impl.OAuth2API.*;

Simplified factory to create an OAuth2Auth for OpenID Connect.
Author:Paulo Lopes
/** * Simplified factory to create an {@link io.vertx.ext.auth.oauth2.OAuth2Auth} for OpenID Connect. * * @author <a href="mailto:plopes@redhat.com">Paulo Lopes</a> */
@VertxGen public interface OpenIDConnectAuth {
Create a OAuth2Auth provider for OpenID Connect Discovery. The discovery will use the given site in the configuration options and attempt to load the well known descriptor. If the discovered config includes a json web key url, it will be also fetched and the JWKs will be loaded into the OAuth provider so tokens can be decoded.
Params:
  • vertx – the vertx instance
  • config – the initial config, it should contain a site url
  • handler – the instantiated Oauth2 provider instance handler
/** * Create a OAuth2Auth provider for OpenID Connect Discovery. The discovery will use the given site in the * configuration options and attempt to load the well known descriptor. * * If the discovered config includes a json web key url, it will be also fetched and the JWKs will be loaded * into the OAuth provider so tokens can be decoded. * * @param vertx the vertx instance * @param config the initial config, it should contain a site url * @param handler the instantiated Oauth2 provider instance handler */
static void discover(final Vertx vertx, final OAuth2ClientOptions config, final Handler<AsyncResult<OAuth2Auth>> handler) { if (config.getSite() == null) { handler.handle(Future.failedFuture("issuer cannot be null")); return; } final HttpClientRequest request = makeRequest(vertx, config, HttpMethod.GET, config.getSite() + "/.well-known/openid-configuration", res -> { if (res.failed()) { handler.handle(Future.failedFuture(res.cause())); return; } final OAuth2Response response = res.result(); if (response.statusCode() != 200) { handler.handle(Future.failedFuture("Bad Response [" + response.statusCode() + "] " + response.body())); return; } if (!response.is("application/json")) { handler.handle(Future.failedFuture("Cannot handle Content-Type: " + response.headers().get("Content-Type"))); return; } final JsonObject json = response.jsonObject(); // issuer validation if (config.isValidateIssuer()) { final String issuerEndpoint = json.getString("issuer"); if (issuerEndpoint != null && !config.getSite().equals(issuerEndpoint)) { handler.handle(Future.failedFuture("issuer validation failed: received [" + issuerEndpoint + "]")); return; } } config.setAuthorizationPath(json.getString("authorization_endpoint")); config.setTokenPath(json.getString("token_endpoint")); config.setIntrospectionPath(json.getString("token_introspection_endpoint")); config.setLogoutPath(json.getString("end_session_endpoint")); config.setRevocationPath(json.getString("revocation_endpoint")); config.setUserInfoPath(json.getString("userinfo_endpoint")); config.setJwkPath(json.getString("jwks_uri")); final OAuth2Auth oidc = OAuth2Auth.create(vertx, config); if (config.getJwkPath() != null) { oidc.loadJWK(v -> { if (v.failed()) { handler.handle(Future.failedFuture(v.cause())); return; } handler.handle(Future.succeededFuture(oidc)); }); } else { handler.handle(Future.succeededFuture(oidc)); } }); // handle errors request.exceptionHandler(t -> handler.handle(Future.failedFuture(t))); // we accept JSON as it is the expected response encoding request.putHeader("Accept", "application/json"); // trigger request.end(); } }