Search in sources :

Example 6 with User

use of oidc.model.User in project OpenConext-oidcng by OpenConext.

the class ResponseAuthenticationConverter method buildUser.

private User buildUser(Assertion assertion, String authenticationRequestID) {
    List<AuthnStatement> authnStatements = assertion.getAuthnStatements();
    AtomicReference<String> authenticatingAuthority = new AtomicReference<>();
    if (!CollectionUtils.isEmpty(authnStatements)) {
        authnStatements.stream().map(as -> as.getAuthnContext().getAuthenticatingAuthorities()).flatMap(List::stream).findAny().ifPresent(aa -> authenticatingAuthority.set(aa.getURI()));
    }
    // need to prevent NullPointer in HashMap merge
    Map<String, Object> attributes = userAttributes.stream().filter(ua -> !ua.customMapping).map(ua -> new Object[] { ua.oidc, ua.multiValue ? getAttributeValues(ua.saml, assertion) : getAttributeValue(ua.saml, assertion) }).filter(oo -> oo[1] != null).collect(Collectors.toMap(oo -> (String) oo[0], oo -> oo[1]));
    this.addDerivedAttributes(attributes);
    AuthenticationRequest authenticationRequest = authenticationRequestRepository.findById(authenticationRequestID).orElseThrow(() -> new IllegalArgumentException("No Authentication Request found for ID: " + authenticationRequestID));
    String clientId = authenticationRequest.getClientId();
    String nameId = assertion.getSubject().getNameID().getValue();
    String eduPersonTargetedId = getAttributeValue("urn:mace:dir:attribute-def:eduPersonTargetedID", assertion);
    String collabPersonId = getAttributeValue("urn:mace:surf.nl:attribute-def:internal-collabPersonId", assertion);
    String sub;
    if (StringUtils.hasText(collabPersonId)) {
        sub = nameId;
        nameId = collabPersonId;
    } else if (StringUtils.hasText(eduPersonTargetedId)) {
        sub = eduPersonTargetedId;
    } else {
        sub = UUID.nameUUIDFromBytes((nameId + "_" + clientId).getBytes()).toString();
    }
    attributes.put("sub", sub);
    List<String> acrClaims = assertion.getAuthnStatements().stream().map(authenticationStatement -> authenticationContextClassReference(authenticationStatement.getAuthnContext().getAuthnContextClassRef())).filter(Optional::isPresent).map(Optional::get).collect(toList());
    return new User(sub, nameId, authenticatingAuthority.get(), clientId, attributes, acrClaims);
}
Also used : java.util(java.util) User(oidc.model.User) OidcSamlAuthentication(oidc.user.OidcSamlAuthentication) OpenSaml4AuthenticationProvider(org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider) org.opensaml.core.xml.schema(org.opensaml.core.xml.schema) AtomicReference(java.util.concurrent.atomic.AtomicReference) Matcher(java.util.regex.Matcher) TypeReference(com.fasterxml.jackson.core.type.TypeReference) XMLObject(org.opensaml.core.xml.XMLObject) UserAttribute(oidc.user.UserAttribute) Resource(org.springframework.core.io.Resource) Converter(org.springframework.core.convert.converter.Converter) Saml2Authentication(org.springframework.security.saml2.provider.service.authentication.Saml2Authentication) SessionAuthenticationException(org.springframework.security.web.authentication.session.SessionAuthenticationException) org.opensaml.saml.saml2.core(org.opensaml.saml.saml2.core) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) IOException(java.io.IOException) Collectors(java.util.stream.Collectors) AuthenticationRequestRepository(oidc.repository.AuthenticationRequestRepository) UserRepository(oidc.repository.UserRepository) Collectors.toList(java.util.stream.Collectors.toList) AuthenticationRequest(oidc.model.AuthenticationRequest) CollectionUtils(org.springframework.util.CollectionUtils) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Pattern(java.util.regex.Pattern) StringUtils(org.springframework.util.StringUtils) User(oidc.model.User) AtomicReference(java.util.concurrent.atomic.AtomicReference) Collectors.toList(java.util.stream.Collectors.toList) XMLObject(org.opensaml.core.xml.XMLObject) AuthenticationRequest(oidc.model.AuthenticationRequest)

Example 7 with User

use of oidc.model.User in project OpenConext-oidcng by OpenConext.

the class ResponseAuthenticationConverterTest method login.

@Test
public void login() throws XMLParserException, UnmarshallingException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    when(authenticationRequestRepository.findById(anyString())).thenReturn(Optional.of(new AuthenticationRequest("id", new Date(), "clientId", "http://some")));
    OidcSamlAuthentication oidcSamlAuthentication = doLogin("saml/authn_response.xml");
    User user = oidcSamlAuthentication.getUser();
    String sub = user.getSub();
    assertEquals("270E4CB4-1C2A-4A96-9AD3-F28C39AD1110", sub);
    assertEquals("urn:collab:person:example.com:admin", oidcSamlAuthentication.getName());
    assertEquals(3, ((List) user.getAttributes().get("eduperson_affiliation")).size());
}
Also used : User(oidc.model.User) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) AuthenticationRequest(oidc.model.AuthenticationRequest) Date(java.util.Date) OidcSamlAuthentication(oidc.user.OidcSamlAuthentication) Test(org.junit.Test)

Example 8 with User

use of oidc.model.User 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)

Example 9 with User

use of oidc.model.User in project OpenConext-oidcng by OpenConext.

the class TokenEndpoint method handleRefreshCodeGrant.

private ResponseEntity handleRefreshCodeGrant(RefreshTokenGrant refreshTokenGrant, OpenIDClient client) throws java.text.ParseException {
    String refreshTokenValue = refreshTokenGrant.getRefreshToken().getValue();
    RefreshToken refreshToken;
    SignedJWT signedJWT = null;
    boolean oldFormat = uuidPattern.matcher(refreshTokenValue).matches();
    if (oldFormat) {
        // Old refreshToken
        refreshToken = refreshTokenRepository.findByInnerValue(refreshTokenValue);
    } else {
        Optional<SignedJWT> optionalSignedJWT = tokenGenerator.parseAndValidateSignedJWT(refreshTokenValue);
        signedJWT = optionalSignedJWT.orElseThrow(() -> new UnauthorizedException("Invalid refresh_token value"));
        String jwtId = signedJWT.getJWTClaimsSet().getJWTID();
        refreshToken = refreshTokenRepository.findByJwtId(jwtId).orElseThrow(() -> new IllegalArgumentException("RefreshToken not found"));
    }
    if (!refreshToken.getClientId().equals(client.getClientId())) {
        throw new InvalidClientException("Client is not authorized for the refresh token");
    }
    if (refreshToken.isExpired(Clock.systemDefaultZone())) {
        throw new UnauthorizedException("Refresh token expired");
    }
    // New tokens will be issued
    refreshTokenRepository.delete(refreshToken);
    // It is possible that the access token is already removed by cron cleanup actions
    Optional<AccessToken> accessToken;
    if (oldFormat) {
        // It is possible that the access token is already removed by cron cleanup actions
        accessToken = accessTokenRepository.findOptionalAccessTokenByValue(refreshToken.getAccessTokenValue());
    } else {
        accessToken = accessTokenRepository.findById(refreshToken.getAccessTokenId());
    }
    accessToken.ifPresent(accessTokenRepository::delete);
    Optional<User> optionalUser;
    if (refreshToken.isClientCredentials()) {
        optionalUser = Optional.empty();
    } else if (oldFormat) {
        optionalUser = Optional.of(tokenGenerator.decryptAccessTokenWithEmbeddedUserInfo(refreshToken.getAccessTokenValue()));
    } else {
        optionalUser = Optional.of(tokenGenerator.decryptAccessTokenWithEmbeddedUserInfo(signedJWT));
    }
    Map<String, Object> body = tokenEndpointResponse(optionalUser, client, refreshToken.getScopes(), Collections.emptyList(), false, null, optionalUser.map(User::getUpdatedAt), Optional.empty());
    return new ResponseEntity<>(body, responseHttpHeaders, HttpStatus.OK);
}
Also used : User(oidc.model.User) SignedJWT(com.nimbusds.jwt.SignedJWT) ResponseEntity(org.springframework.http.ResponseEntity) RefreshToken(oidc.model.RefreshToken) AccessToken(oidc.model.AccessToken) UnauthorizedException(oidc.exceptions.UnauthorizedException) InvalidClientException(oidc.exceptions.InvalidClientException)

Example 10 with User

use of oidc.model.User in project OpenConext-oidcng by OpenConext.

the class TokenEndpoint method tokenEndpointResponse.

private Map<String, Object> tokenEndpointResponse(Optional<User> user, OpenIDClient client, List<String> scopes, List<String> idTokenClaims, boolean clientCredentials, String nonce, Optional<Long> authorizationTime, Optional<String> authorizationCodeId) {
    Map<String, Object> map = new LinkedHashMap<>();
    EncryptedTokenValue encryptedAccessToken = user.map(u -> tokenGenerator.generateAccessTokenWithEmbeddedUserInfo(u, client, scopes)).orElse(tokenGenerator.generateAccessToken(client, scopes));
    String sub = user.map(User::getSub).orElse(client.getClientId());
    String unspecifiedUrnHash = user.map(u -> KeyGenerator.oneWayHash(u.getUnspecifiedNameId(), this.salt)).orElse(null);
    AccessToken accessToken = new AccessToken(encryptedAccessToken.getJwtId(), sub, client.getClientId(), scopes, encryptedAccessToken.getKeyId(), accessTokenValidity(client), !user.isPresent(), authorizationCodeId.orElse(null), unspecifiedUrnHash);
    accessToken = accessTokenRepository.insert(accessToken);
    map.put("access_token", encryptedAccessToken.getValue());
    map.put("token_type", "Bearer");
    if (client.getGrants().contains(GrantType.REFRESH_TOKEN.getValue())) {
        EncryptedTokenValue encryptedRefreshToken = user.map(u -> tokenGenerator.generateRefreshTokenWithEmbeddedUserInfo(u, client)).orElse(tokenGenerator.generateRefreshToken(client));
        String refreshTokenValue = encryptedRefreshToken.getValue();
        refreshTokenRepository.insert(new RefreshToken(encryptedRefreshToken.getJwtId(), accessToken, refreshTokenValidity(client)));
        map.put("refresh_token", refreshTokenValue);
    }
    map.put("expires_in", client.getAccessTokenValidity());
    if (isOpenIDRequest(scopes) && !clientCredentials) {
        TokenValue tokenValue = tokenGenerator.generateIDTokenForTokenEndpoint(user, client, nonce, idTokenClaims, scopes, authorizationTime);
        map.put("id_token", tokenValue.getValue());
    }
    return map;
}
Also used : AuthorizationCodeRepository(oidc.repository.AuthorizationCodeRepository) CodeVerifierMissingException(oidc.exceptions.CodeVerifierMissingException) Date(java.util.Date) JOSEException(com.nimbusds.jose.JOSEException) ClientAuthentication(com.nimbusds.oauth2.sdk.auth.ClientAuthentication) User(oidc.model.User) MACVerifier(com.nimbusds.jose.crypto.MACVerifier) RefreshTokenGrant(com.nimbusds.oauth2.sdk.RefreshTokenGrant) Map(java.util.Map) ClientSecretJWT(com.nimbusds.oauth2.sdk.auth.ClientSecretJWT) CodeVerifier(com.nimbusds.oauth2.sdk.pkce.CodeVerifier) PostMapping(org.springframework.web.bind.annotation.PostMapping) APPLICATION_JSON(org.apache.http.entity.ContentType.APPLICATION_JSON) HttpHeaders(org.springframework.http.HttpHeaders) MediaType(org.springframework.http.MediaType) SignedJWT(com.nimbusds.jwt.SignedJWT) RestController(org.springframework.web.bind.annotation.RestController) Collectors(java.util.stream.Collectors) TokenRequest(com.nimbusds.oauth2.sdk.TokenRequest) List(java.util.List) OpenIDClientRepository(oidc.repository.OpenIDClientRepository) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Scope(oidc.model.Scope) Optional(java.util.Optional) TokenGenerator(oidc.secure.TokenGenerator) LogFactory(org.apache.commons.logging.LogFactory) Pattern(java.util.regex.Pattern) JWTAuthentication(com.nimbusds.oauth2.sdk.auth.JWTAuthentication) CodeChallengeMethod(com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod) AuthorizationCode(oidc.model.AuthorizationCode) BadCredentialsException(org.springframework.security.authentication.BadCredentialsException) GrantType(com.nimbusds.oauth2.sdk.GrantType) MessageDigest(java.security.MessageDigest) ServletUtils(com.nimbusds.oauth2.sdk.http.ServletUtils) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) RedirectMismatchException(oidc.exceptions.RedirectMismatchException) JWTAuthorizationGrantsException(oidc.exceptions.JWTAuthorizationGrantsException) UnknownClientException(oidc.exceptions.UnknownClientException) RefreshTokenRepository(oidc.repository.RefreshTokenRepository) Value(org.springframework.beans.factory.annotation.Value) LinkedHashMap(java.util.LinkedHashMap) CodeChallenge(com.nimbusds.oauth2.sdk.pkce.CodeChallenge) KeyGenerator(oidc.crypto.KeyGenerator) HttpServletRequest(javax.servlet.http.HttpServletRequest) TokenValue(oidc.model.TokenValue) InvalidClientException(oidc.exceptions.InvalidClientException) ParseException(com.nimbusds.oauth2.sdk.ParseException) PlainClientSecret(com.nimbusds.oauth2.sdk.auth.PlainClientSecret) OpenIDClient(oidc.model.OpenIDClient) MDCContext(oidc.log.MDCContext) JWTRequest(oidc.secure.JWTRequest) ClientCredentialsGrant(com.nimbusds.oauth2.sdk.ClientCredentialsGrant) HTTPRequest(com.nimbusds.oauth2.sdk.http.HTTPRequest) AuthorizationGrant(com.nimbusds.oauth2.sdk.AuthorizationGrant) AuthorizationCodeGrant(com.nimbusds.oauth2.sdk.AuthorizationCodeGrant) TokenAlreadyUsedException(oidc.exceptions.TokenAlreadyUsedException) InvalidGrantException(oidc.exceptions.InvalidGrantException) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException) AccessTokenRepository(oidc.repository.AccessTokenRepository) EncryptedTokenValue(oidc.model.EncryptedTokenValue) UserRepository(oidc.repository.UserRepository) HttpStatus(org.springframework.http.HttpStatus) AccessToken(oidc.model.AccessToken) BadJOSEException(com.nimbusds.jose.proc.BadJOSEException) UnauthorizedException(oidc.exceptions.UnauthorizedException) Clock(java.time.Clock) Log(org.apache.commons.logging.Log) ResponseEntity(org.springframework.http.ResponseEntity) NoSuchProviderException(java.security.NoSuchProviderException) Collections(java.util.Collections) AuthorizationEndpoint.validateScopes(oidc.endpoints.AuthorizationEndpoint.validateScopes) RefreshToken(oidc.model.RefreshToken) RefreshToken(oidc.model.RefreshToken) AccessToken(oidc.model.AccessToken) EncryptedTokenValue(oidc.model.EncryptedTokenValue) LinkedHashMap(java.util.LinkedHashMap) TokenValue(oidc.model.TokenValue) EncryptedTokenValue(oidc.model.EncryptedTokenValue)

Aggregations

User (oidc.model.User)17 SignedJWT (com.nimbusds.jwt.SignedJWT)7 OpenIDClient (oidc.model.OpenIDClient)7 AuthorizationCode (oidc.model.AuthorizationCode)5 Test (org.junit.Test)5 AbstractIntegrationTest (oidc.AbstractIntegrationTest)4 UnauthorizedException (oidc.exceptions.UnauthorizedException)4 AccessToken (oidc.model.AccessToken)4 EncryptedTokenValue (oidc.model.EncryptedTokenValue)4 OidcSamlAuthentication (oidc.user.OidcSamlAuthentication)4 HTTPRequest (com.nimbusds.oauth2.sdk.http.HTTPRequest)3 Date (java.util.Date)3 UnknownClientException (oidc.exceptions.UnknownClientException)3 AuthenticationRequest (oidc.model.AuthenticationRequest)3 TokenValue (oidc.model.TokenValue)3 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)2 ClientAuthentication (com.nimbusds.oauth2.sdk.auth.ClientAuthentication)2 PlainClientSecret (com.nimbusds.oauth2.sdk.auth.PlainClientSecret)2 LinkedHashMap (java.util.LinkedHashMap)2 Map (java.util.Map)2