Search in sources :

Example 1 with ResponseMode

use of com.nimbusds.oauth2.sdk.ResponseMode in project Kustvakt by KorAP.

the class OpenIdResponseHandler method createAuthorizationErrorResponse.

/**
 * According to OpenID connect core 1.0 specification, all
 * authentication errors must be represented through
 * AuthenticationErrorResponse. Moreover, for authorization code
 * flow, the error response parameters must be added to the
 * redirect URI as query parameters, unless a different response
 * mode was specified.
 *
 * {@link AuthorizationErrorResponse} defines specific
 * {@link ErrorObject}s regarding OAUTH2 errors.
 * {@link AuthenticationErrorResponse} defines additional
 * ErrorObjects regarding OpenID connect authenticaition errors.
 *
 * @param e
 *            a {@link KustvaktException}
 * @param isAuthentication
 * @param redirectURI
 * @param state
 * @param responseMode
 * @return a redirect uri with error response parameters as part
 *         of query parameters
 */
public Response createAuthorizationErrorResponse(KustvaktException e, boolean isAuthentication, URI redirectURI, State state, ResponseMode responseMode) {
    ErrorObject errorObject = createErrorObject(e);
    errorObject = errorObject.setDescription(e.getMessage());
    if (redirectURI == null) {
        return Response.status(errorObject.getHTTPStatusCode()).entity(errorObject.toJSONObject()).build();
    }
    URI uri = null;
    if (isAuthentication) {
        uri = new AuthenticationErrorResponse(redirectURI, errorObject, state, responseMode).toURI();
    } else {
        uri = new AuthorizationErrorResponse(redirectURI, errorObject, state, responseMode).toURI();
    }
    ResponseBuilder builder = Response.temporaryRedirect(uri).type(MediaType.APPLICATION_FORM_URLENCODED);
    return builder.build();
}
Also used : AuthorizationErrorResponse(com.nimbusds.oauth2.sdk.AuthorizationErrorResponse) AuthenticationErrorResponse(com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) ResponseBuilder(javax.ws.rs.core.Response.ResponseBuilder) URI(java.net.URI)

Example 2 with ResponseMode

use of com.nimbusds.oauth2.sdk.ResponseMode in project Kustvakt by KorAP.

the class OAuth2WithOpenIdController method requestAuthorizationCode.

/**
 * Required parameters for OpenID authentication requests:
 *
 * <ul>
 * <li>scope: MUST contain "openid" for OpenID Connect
 * requests</li>
 * <li>response_type: only "code" is supported</li>
 * <li>client_id: client identifier given by Kustvakt during
 * client registration</li>
 * <li>redirect_uri: MUST match a pre-registered redirect uri
 * during client registration</li>
 * </ul>
 *
 * Other parameters:
 *
 * <ul>
 * <li>state (recommended): Opaque value used to maintain state
 * between the request and the callback.</li>
 * <li>response_mode (optional) : mechanism to be used for
 * returning parameters, only "query" is supported</li>
 * <li>nonce (optional): String value used to associate a Client
 * session with an ID Token,
 * and to mitigate replay attacks. </li>
 * <li>display (optional): specifies how the Authorization Server
 * displays the authentication and consent user interface
 * pages. Options: page (default), popup, touch, wap. This
 * parameter is more relevant for Kalamar. </li>
 * <li>prompt (optional): specifies if the Authorization Server
 * prompts the End-User for reauthentication and consent. Defined
 * values: none, login, consent, select_account </li>
 * <li>max_age (optional): maximum Authentication Age.</li>
 * <li>ui_locales (optional): preferred languages and scripts for
 * the user interface represented as a space-separated list of
 * BCP47 [RFC5646] </li>
 * <li>id_token_hint (optional): ID Token previously issued by the
 * Authorization Server being passed as a hint</li>
 * <li>login_hint (optional): hint to the Authorization Server
 * about the login identifier the End-User might use to log
 * in</li>
 * <li>acr_values (optional): requested Authentication Context
 * Class Reference values. </li>
 * </ul>
 *
 * @see "OpenID Connect Core 1.0 specification"
 *
 * @param request
 * @param context
 * @param form
 * @return a redirect to client redirect uri
 */
@POST
@Path("authorize")
@ResourceFilters({ AuthenticationFilter.class, BlockingFilter.class })
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
public Response requestAuthorizationCode(@Context HttpServletRequest request, @Context SecurityContext context, MultivaluedMap<String, String> form) {
    TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
    String username = tokenContext.getUsername();
    ZonedDateTime authTime = tokenContext.getAuthenticationTime();
    Map<String, String> map = MapUtils.toMap(form);
    State state = authzService.retrieveState(map);
    ResponseMode responseMode = authzService.retrieveResponseMode(map);
    boolean isAuthentication = false;
    if (map.containsKey("scope") && map.get("scope").contains("openid")) {
        isAuthentication = true;
    }
    URI uri = null;
    try {
        scopeService.verifyScope(tokenContext, OAuth2Scope.AUTHORIZE);
        if (isAuthentication) {
            authzService.checkRedirectUriParam(map);
        }
        uri = authzService.requestAuthorizationCode(form, username, isAuthentication, authTime);
    } catch (ParseException e) {
        return openIdResponseHandler.createErrorResponse(e, state);
    } catch (KustvaktException e) {
        return openIdResponseHandler.createAuthorizationErrorResponse(e, isAuthentication, e.getRedirectUri(), state, responseMode);
    }
    ResponseBuilder builder = Response.temporaryRedirect(uri);
    return builder.build();
}
Also used : TokenContext(de.ids_mannheim.korap.security.context.TokenContext) KustvaktException(de.ids_mannheim.korap.exceptions.KustvaktException) ZonedDateTime(java.time.ZonedDateTime) ResponseMode(com.nimbusds.oauth2.sdk.ResponseMode) State(com.nimbusds.oauth2.sdk.id.State) ParseException(com.nimbusds.oauth2.sdk.ParseException) ResponseBuilder(javax.ws.rs.core.Response.ResponseBuilder) URI(java.net.URI) Path(javax.ws.rs.Path) ResourceFilters(com.sun.jersey.spi.container.ResourceFilters) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces)

Example 3 with ResponseMode

use of com.nimbusds.oauth2.sdk.ResponseMode in project ddf by codice.

the class OidcHandlerConfigurationImpl method setProperties.

public void setProperties(Map<String, Object> properties) {
    if (properties == null || properties.isEmpty()) {
        LOGGER.warn("Received null or empty properties. Cannot update.");
        return;
    }
    idpType = (String) properties.getOrDefault(IDP_TYPE_KEY, idpType);
    clientId = (String) properties.getOrDefault(CLIENT_ID_KEY, idpType);
    realm = (String) properties.getOrDefault(REALM_KEY, realm);
    secret = (String) properties.getOrDefault(SECRET_KEY, secret);
    discoveryUri = (String) properties.getOrDefault(DISCOVERY_URI_KEY, discoveryUri);
    baseUri = (String) properties.getOrDefault(BASE_URI_KEY, baseUri);
    scope = (String) properties.getOrDefault(SCOPE_KEY, scope);
    useNonce = (boolean) properties.getOrDefault(USE_NONCE_KEY, useNonce);
    responseType = (String) properties.getOrDefault(RESPONSE_TYPE_KEY, responseType);
    responseMode = (String) properties.getOrDefault(RESPONSE_MODE_KEY, responseMode);
    logoutUri = (String) properties.getOrDefault(LOGOUT_URI_KEY, logoutUri);
    connectTimeout = (int) properties.getOrDefault(CONNECT_TIMEOUT_KEY, connectTimeout);
    readTimeout = (int) properties.getOrDefault(READ_TIMEOUT_KEY, readTimeout);
    // TODO - Remove if fragment response_mode is supported
    if (IMPLICIT_FLOWS.contains(new ResponseType(responseType))) {
        responseMode = "form_post";
    }
    oidcConfiguration = createOidcConfiguration(idpType, realm, baseUri);
    oidcConfiguration.setClientId(clientId);
    oidcConfiguration.setDiscoveryURI(discoveryUri);
    oidcConfiguration.setSecret(secret);
    oidcConfiguration.setScope(scope);
    oidcConfiguration.setResponseType(responseType);
    oidcConfiguration.setResponseMode(responseMode);
    oidcConfiguration.setUseNonce(useNonce);
    oidcConfiguration.setLogoutUrl(logoutUri);
    oidcConfiguration.setWithState(true);
    oidcConfiguration.setConnectTimeout(connectTimeout);
    oidcConfiguration.setReadTimeout(readTimeout);
    try {
        testConnection();
    } catch (TechnicalException e) {
        LOGGER.warn("Failed to validate OIDC handler configuration. Please review configuration and ensure the auth server is reachable", e);
    }
}
Also used : TechnicalException(org.pac4j.core.exception.TechnicalException) ResponseType(com.nimbusds.oauth2.sdk.ResponseType)

Example 4 with ResponseMode

use of com.nimbusds.oauth2.sdk.ResponseMode in project OpenConext-oidcng by OpenConext.

the class AuthorizationEndpoint method doAuthorization.

private ModelAndView doAuthorization(MultiValueMap<String, String> parameters, OidcSamlAuthentication samlAuthentication, HttpServletRequest request, boolean consentRequired) throws ParseException, CertificateException, JOSEException, IOException, BadJOSEException, java.text.ParseException, URISyntaxException {
    AuthorizationRequest authenticationRequest = AuthorizationRequest.parse(parameters);
    Scope scope = authenticationRequest.getScope();
    boolean isOpenIdClient = scope != null && isOpenIDRequest(scope.toStringList());
    String clientId = authenticationRequest.getClientID().getValue();
    OpenIDClient client = openIDClientRepository.findOptionalByClientId(clientId).orElseThrow(() -> new UnknownClientException(clientId));
    MDCContext.mdcContext("action", "Authorize", "rp", client.getClientId());
    if (isOpenIdClient) {
        AuthenticationRequest oidcAuthenticationRequest = AuthenticationRequest.parse(parameters);
        if (oidcAuthenticationRequest.specifiesRequestObject()) {
            oidcAuthenticationRequest = JWTRequest.parse(oidcAuthenticationRequest, client);
            LOG.debug("/oidc/authorize with JWT 'request'");
        }
        // swap reference
        authenticationRequest = oidcAuthenticationRequest;
    }
    State state = authenticationRequest.getState();
    String redirectURI = validateRedirectionURI(authenticationRequest.getRedirectionURI(), client).getRedirectURI();
    List<String> scopes = validateScopes(openIDClientRepository, authenticationRequest.getScope(), client);
    ResponseType responseType = validateGrantType(authenticationRequest, client);
    User user = samlAuthentication.getUser();
    MDCContext.mdcContext(user);
    if (scope != null) {
        List<String> scopeList = scope.toStringList();
        boolean apiScopeRequested = !(scopeList.size() == 0 || (scopeList.size() == 1 && scopeList.contains("openid")));
        Set<String> filteredScopes = scopeList.stream().filter(s -> !s.equalsIgnoreCase("openid")).map(String::toLowerCase).collect(toSet());
        List<OpenIDClient> resourceServers = openIDClientRepository.findByScopes_NameIn(filteredScopes);
        Prompt prompt = authenticationRequest.getPrompt();
        boolean consentFromPrompt = prompt != null && prompt.toStringList().contains("consent");
        /*
             * We prompt for consent when the following conditions are met:
             *   Consent feature toggle is on
             *   The RP has requested scope(s) other then openid
             *   Manage attribute "oidc:consentRequired" is true for the RP or the RP has explicitly asked for consent
             *   There is at least one ResourceServer that has the requested scope(s) configured in manage
             */
        if (consentRequired && apiScopeRequested && (consentFromPrompt || client.isConsentRequired()) && resourceServers.size() > 0) {
            LOG.info("Asking for consent for User " + user + " and scopes " + scopes);
            return doConsent(parameters, client, filteredScopes, resourceServers);
        }
    }
    // We do not provide SSO as does EB not - up to the identity provider
    logout(request);
    ResponseMode responseMode = authenticationRequest.impliedResponseMode();
    if (responseType.impliesCodeFlow()) {
        AuthorizationCode authorizationCode = createAndSaveAuthorizationCode(authenticationRequest, client, user);
        LOG.debug(String.format("Returning authorizationCode flow %s %s", ResponseMode.FORM_POST, redirectURI));
        if (responseMode.equals(ResponseMode.FORM_POST)) {
            Map<String, String> body = new HashMap<>();
            body.put("redirect_uri", redirectURI);
            body.put("code", authorizationCode.getCode());
            if (state != null && StringUtils.hasText(state.getValue())) {
                body.put("state", state.getValue());
            }
            return new ModelAndView("form_post", body);
        }
        return new ModelAndView(new RedirectView(authorizationRedirect(redirectURI, state, authorizationCode.getCode(), responseMode.equals(ResponseMode.FRAGMENT))));
    } else if (responseType.impliesImplicitFlow() || responseType.impliesHybridFlow()) {
        if (responseType.impliesImplicitFlow()) {
            // User information is encrypted in access token
            LOG.debug("Deleting user " + user.getSub());
            userRepository.delete(user);
        }
        Map<String, Object> body = authorizationEndpointResponse(user, client, authenticationRequest, scopes, responseType, state);
        LOG.debug(String.format("Returning implicit flow %s %s", ResponseMode.FORM_POST, redirectURI));
        if (responseMode.equals(ResponseMode.FORM_POST)) {
            body.put("redirect_uri", redirectURI);
            return new ModelAndView("form_post", body);
        }
        if (responseMode.equals(ResponseMode.QUERY)) {
            UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(redirectURI);
            body.forEach(builder::queryParam);
            return new ModelAndView(new RedirectView(builder.toUriString()));
        }
        if (responseMode.equals(ResponseMode.FRAGMENT)) {
            UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(redirectURI);
            String fragment = body.entrySet().stream().map(entry -> String.format("%s=%s", entry.getKey(), entry.getValue())).collect(Collectors.joining("&"));
            builder.fragment(fragment);
            return new ModelAndView(new RedirectView(builder.toUriString()));
        }
        throw new IllegalArgumentException("Response mode " + responseMode + " not supported");
    }
    throw new IllegalArgumentException("Not yet implemented response_type: " + responseType.toString());
}
Also used : AuthorizationCode(oidc.model.AuthorizationCode) AuthorizationRequest(com.nimbusds.oauth2.sdk.AuthorizationRequest) User(oidc.model.User) UnknownClientException(oidc.exceptions.UnknownClientException) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) OpenIDClient(oidc.model.OpenIDClient) ModelAndView(org.springframework.web.servlet.ModelAndView) ResponseType(com.nimbusds.oauth2.sdk.ResponseType) Scope(com.nimbusds.oauth2.sdk.Scope) ResponseMode(com.nimbusds.oauth2.sdk.ResponseMode) State(com.nimbusds.oauth2.sdk.id.State) UriComponentsBuilder(org.springframework.web.util.UriComponentsBuilder) RedirectView(org.springframework.web.servlet.view.RedirectView) Prompt(com.nimbusds.openid.connect.sdk.Prompt) AuthenticationRequest(com.nimbusds.openid.connect.sdk.AuthenticationRequest) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) MultiValueMap(org.springframework.util.MultiValueMap) LinkedMultiValueMap(org.springframework.util.LinkedMultiValueMap)

Aggregations

ResponseMode (com.nimbusds.oauth2.sdk.ResponseMode)2 ResponseType (com.nimbusds.oauth2.sdk.ResponseType)2 State (com.nimbusds.oauth2.sdk.id.State)2 URI (java.net.URI)2 ResponseBuilder (javax.ws.rs.core.Response.ResponseBuilder)2 AuthorizationErrorResponse (com.nimbusds.oauth2.sdk.AuthorizationErrorResponse)1 AuthorizationRequest (com.nimbusds.oauth2.sdk.AuthorizationRequest)1 ErrorObject (com.nimbusds.oauth2.sdk.ErrorObject)1 ParseException (com.nimbusds.oauth2.sdk.ParseException)1 Scope (com.nimbusds.oauth2.sdk.Scope)1 AuthenticationErrorResponse (com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse)1 AuthenticationRequest (com.nimbusds.openid.connect.sdk.AuthenticationRequest)1 Prompt (com.nimbusds.openid.connect.sdk.Prompt)1 ResourceFilters (com.sun.jersey.spi.container.ResourceFilters)1 KustvaktException (de.ids_mannheim.korap.exceptions.KustvaktException)1 TokenContext (de.ids_mannheim.korap.security.context.TokenContext)1 ZonedDateTime (java.time.ZonedDateTime)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1