Search in sources :

Example 1 with AccessToken

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

the class AuthorizationEndpoint method authorizationEndpointResponse.

private Map<String, Object> authorizationEndpointResponse(User user, OpenIDClient client, AuthorizationRequest authorizationRequest, List<String> scopes, ResponseType responseType, State state) {
    Map<String, Object> result = new LinkedHashMap<>();
    EncryptedTokenValue encryptedAccessToken = tokenGenerator.generateAccessTokenWithEmbeddedUserInfo(user, client, scopes);
    if (responseType.contains(ResponseType.Value.TOKEN.getValue()) || !isOpenIDRequest(authorizationRequest)) {
        String unspecifiedUrnHash = KeyGenerator.oneWayHash(user.getUnspecifiedNameId(), this.salt);
        AccessToken accessToken = new AccessToken(encryptedAccessToken.getJwtId(), user.getSub(), client.getClientId(), scopes, encryptedAccessToken.getKeyId(), accessTokenValidity(client), false, null, unspecifiedUrnHash);
        accessTokenRepository.insert(accessToken);
        result.put("access_token", encryptedAccessToken.getValue());
        result.put("token_type", "Bearer");
    }
    if (responseType.contains(ResponseType.Value.CODE.getValue())) {
        AuthorizationCode authorizationCode = createAndSaveAuthorizationCode(authorizationRequest, client, user);
        result.put("code", authorizationCode.getCode());
    }
    if (responseType.contains(OIDCResponseTypeValue.ID_TOKEN.getValue()) && isOpenIDRequest(scopes) && isOpenIDRequest(authorizationRequest)) {
        AuthenticationRequest authenticationRequest = (AuthenticationRequest) authorizationRequest;
        List<String> claims = getClaims(authorizationRequest);
        TokenValue tokenValue = tokenGenerator.generateIDTokenForAuthorizationEndpoint(user, client, authenticationRequest.getNonce(), responseType, encryptedAccessToken.getValue(), claims, Optional.ofNullable((String) result.get("code")), state);
        result.put("id_token", tokenValue.getValue());
    }
    result.put("expires_in", client.getAccessTokenValidity());
    if (state != null) {
        result.put("state", state.getValue());
    }
    return result;
}
Also used : AuthorizationCode(oidc.model.AuthorizationCode) AccessToken(oidc.model.AccessToken) EncryptedTokenValue(oidc.model.EncryptedTokenValue) AuthenticationRequest(com.nimbusds.openid.connect.sdk.AuthenticationRequest) LinkedHashMap(java.util.LinkedHashMap) TokenValue(oidc.model.TokenValue) EncryptedTokenValue(oidc.model.EncryptedTokenValue)

Example 2 with AccessToken

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

the class IntrospectEndpoint method introspect.

@PostMapping(value = { "oidc/introspect" }, consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ResponseEntity<Map<String, Object>> introspect(HttpServletRequest request) throws ParseException, IOException, java.text.ParseException {
    HTTPRequest httpRequest = ServletUtils.createHTTPRequest(request);
    TokenIntrospectionRequest tokenIntrospectionRequest = TokenIntrospectionRequest.parse(httpRequest);
    ClientAuthentication clientAuthentication = tokenIntrospectionRequest.getClientAuthentication();
    String accessTokenValue = tokenIntrospectionRequest.getToken().getValue();
    // https://tools.ietf.org/html/rfc7662 is vague about the authorization requirements, but we enforce basic auth
    if (!(clientAuthentication instanceof PlainClientSecret)) {
        LOG.warn("No authentication present");
        throw new UnauthorizedException("Invalid user / secret");
    }
    String clientId = clientAuthentication.getClientID().getValue();
    OpenIDClient resourceServer = openIDClientRepository.findOptionalByClientId(clientId).orElseThrow(() -> new UnknownClientException(clientId));
    MDCContext.mdcContext("action", "Introspect", "rp", resourceServer.getClientId(), "accessTokenValue", accessTokenValue);
    if (!secretsMatch((PlainClientSecret) clientAuthentication, resourceServer)) {
        LOG.warn("Secret does not match for RS " + resourceServer.getClientId());
        throw new UnauthorizedException("Invalid user / secret");
    }
    if (!resourceServer.isResourceServer()) {
        LOG.warn("RS required for not configured for RP " + resourceServer.getClientId());
        throw new UnauthorizedException("Requires ResourceServer");
    }
    Optional<SignedJWT> optionalSignedJWT = tokenGenerator.parseAndValidateSignedJWT(accessTokenValue);
    if (!optionalSignedJWT.isPresent()) {
        LOG.warn("Invalid access_token " + accessTokenValue);
        return ResponseEntity.ok(Collections.singletonMap("active", false));
    }
    SignedJWT signedJWT = optionalSignedJWT.get();
    String jwtId = signedJWT.getJWTClaimsSet().getJWTID();
    Optional<AccessToken> optionalAccessToken = accessTokenRepository.findByJwtId(jwtId);
    if (!optionalAccessToken.isPresent()) {
        LOG.warn("No access_token found " + accessTokenValue);
        return ResponseEntity.ok(Collections.singletonMap("active", false));
    }
    AccessToken accessToken = optionalAccessToken.get();
    if (accessToken.isExpired(Clock.systemDefaultZone())) {
        LOG.warn("Access token is expired " + accessTokenValue);
        return ResponseEntity.ok(Collections.singletonMap("active", false));
    }
    List<String> scopes = accessToken.getScopes();
    Map<String, Object> result = new TreeMap<>();
    boolean isUserAccessToken = !accessToken.isClientCredentials();
    if (isUserAccessToken) {
        OpenIDClient openIDClient = openIDClientRepository.findOptionalByClientId(accessToken.getClientId()).orElseThrow(() -> new UnknownClientException(accessToken.getClientId()));
        if (!openIDClient.getClientId().equals(resourceServer.getClientId()) && !openIDClient.getAllowedResourceServers().contains(resourceServer.getClientId())) {
            throw new UnauthorizedException(String.format("RP %s is not allowed to use the API of resource server %s. Allowed resource servers are %s", accessToken.getClientId(), resourceServer.getClientId(), openIDClient.getAllowedResourceServers()));
        }
        User user = tokenGenerator.decryptAccessTokenWithEmbeddedUserInfo(signedJWT);
        result.put("updated_at", user.getUpdatedAt());
        if (resourceServer.isIncludeUnspecifiedNameID()) {
            result.put("unspecified_id", user.getUnspecifiedNameId());
        }
        result.put("authenticating_authority", user.getAuthenticatingAuthority());
        result.put("sub", user.getSub());
        result.putAll(user.getAttributes());
        List<String> acrClaims = user.getAcrClaims();
        if (!CollectionUtils.isEmpty(acrClaims)) {
            result.put("acr", String.join(" ", acrClaims));
        }
        boolean validPseudonymisation = validPseudonymisation(result, resourceServer, openIDClient);
        if (!validPseudonymisation && enforceEduidResourceServerLinkedAccount) {
            LOG.warn(String.format("Pseudonymisation failed. No eduperson_principal_name for RS %s", resourceServer.getClientId()));
            return ResponseEntity.ok(Collections.singletonMap("active", false));
        }
    }
    // The following claims can not be overridden by the
    result.put("active", true);
    result.put("scope", String.join(" ", scopes));
    result.put("client_id", accessToken.getClientId());
    result.put("exp", accessToken.getExpiresIn().getTime() / 1000L);
    result.put("sub", accessToken.getSub());
    result.put("iss", issuer);
    result.put("token_type", "Bearer");
    LOG.debug(String.format("Returning introspect active %s for RS %s", true, resourceServer.getClientId()));
    return ResponseEntity.ok(result);
}
Also used : HTTPRequest(com.nimbusds.oauth2.sdk.http.HTTPRequest) User(oidc.model.User) UnknownClientException(oidc.exceptions.UnknownClientException) OpenIDClient(oidc.model.OpenIDClient) TokenIntrospectionRequest(com.nimbusds.oauth2.sdk.TokenIntrospectionRequest) SignedJWT(com.nimbusds.jwt.SignedJWT) TreeMap(java.util.TreeMap) PlainClientSecret(com.nimbusds.oauth2.sdk.auth.PlainClientSecret) AccessToken(oidc.model.AccessToken) UnauthorizedException(oidc.exceptions.UnauthorizedException) ClientAuthentication(com.nimbusds.oauth2.sdk.auth.ClientAuthentication) PostMapping(org.springframework.web.bind.annotation.PostMapping)

Example 3 with AccessToken

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

the class TokenController method convertToken.

private Map<String, Object> convertToken(AccessToken token) {
    Map<String, Object> result = new HashMap<>();
    result.put("id", token.getId());
    Optional<OpenIDClient> optionalClient = openIDClientRepository.findOptionalByClientId(token.getClientId());
    if (!optionalClient.isPresent()) {
        return result;
    }
    OpenIDClient openIDClient = optionalClient.get();
    result.put("clientId", openIDClient.getClientId());
    result.put("clientName", openIDClient.getName());
    List<OpenIDClient> resourceServers = openIDClient.getAllowedResourceServers().stream().map(rs -> openIDClientRepository.findOptionalByClientId(rs)).filter(Optional::isPresent).map(Optional::get).collect(toList());
    result.put("audiences", resourceServers.stream().map(OpenIDClient::getName));
    result.put("createdAt", token.getCreatedAt());
    result.put("expiresIn", token.getExpiresIn());
    result.put("type", token instanceof RefreshToken ? TokenType.REFRESH : TokenType.ACCESS);
    Map<String, Scope> allScopes = resourceServers.stream().map(OpenIDClient::getScopes).flatMap(List::stream).filter(distinctByKey(Scope::getName)).collect(toMap(Scope::getName, s -> s));
    List<Scope> scopes = token.getScopes().stream().filter(name -> !name.equalsIgnoreCase("openid")).map(allScopes::get).filter(Objects::nonNull).collect(toList());
    result.put("scopes", scopes);
    return result;
}
Also used : TokenType(oidc.model.TokenType) RequestParam(org.springframework.web.bind.annotation.RequestParam) java.util(java.util) URLDecoder(java.net.URLDecoder) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) RefreshTokenRepository(oidc.repository.RefreshTokenRepository) Function(java.util.function.Function) Value(org.springframework.beans.factory.annotation.Value) RequestBody(org.springframework.web.bind.annotation.RequestBody) KeyGenerator(oidc.crypto.KeyGenerator) PutMapping(org.springframework.web.bind.annotation.PutMapping) Charset(java.nio.charset.Charset) Collectors.toMap(java.util.stream.Collectors.toMap) GetMapping(org.springframework.web.bind.annotation.GetMapping) OpenIDClient(oidc.model.OpenIDClient) TokenRepresentation(oidc.model.TokenRepresentation) Predicate(java.util.function.Predicate) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AccessTokenRepository(oidc.repository.AccessTokenRepository) RestController(org.springframework.web.bind.annotation.RestController) Collectors(java.util.stream.Collectors) HttpStatus(org.springframework.http.HttpStatus) AccessToken(oidc.model.AccessToken) Collectors.toList(java.util.stream.Collectors.toList) Stream(java.util.stream.Stream) OpenIDClientRepository(oidc.repository.OpenIDClientRepository) Scope(oidc.model.Scope) Log(org.apache.commons.logging.Log) ResponseEntity(org.springframework.http.ResponseEntity) LogFactory(org.apache.commons.logging.LogFactory) Authentication(org.springframework.security.core.Authentication) UnsupportedEncodingException(java.io.UnsupportedEncodingException) RefreshToken(oidc.model.RefreshToken) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) OpenIDClient(oidc.model.OpenIDClient) RefreshToken(oidc.model.RefreshToken) Scope(oidc.model.Scope) Collectors.toList(java.util.stream.Collectors.toList)

Example 4 with AccessToken

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

the class KeyRolloverTest method rolloverSigningKeys.

@Test
public void rolloverSigningKeys() throws GeneralSecurityException, ParseException, IOException {
    resetAndCreateSigningKeys(3);
    final List<String> signingKeys = mongoTemplate.findAll(SigningKey.class).stream().map(SigningKey::getKeyId).sorted().collect(toList());
    assertEquals(3, signingKeys.size());
    List<AccessToken> tokens = IntStream.rangeClosed(0, 10).mapToObj(i -> accessToken("val" + i, signingKeys.get(i % 2))).collect(toList());
    mongoTemplate.bulkOps(BulkOperations.BulkMode.ORDERED, AccessToken.class).remove(new Query()).insert(tokens).execute();
    KeyRollover keyRollover = new KeyRollover(tokenGenerator, mongoTemplate, true, sequenceRepository);
    keyRollover.rollover();
    List<String> keys = mongoTemplate.findAll(SigningKey.class).stream().map(SigningKey::getKeyId).sorted().collect(toList());
    // would expect 4, but one signing key is cleaned up as it is not used in
    assertEquals(3, keys.size());
}
Also used : IntStream(java.util.stream.IntStream) Arrays(java.util.Arrays) BulkOperations(org.springframework.data.mongodb.core.BulkOperations) Date(java.util.Date) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) IOException(java.io.IOException) Query(org.springframework.data.mongodb.core.query.Query) AccessToken(oidc.model.AccessToken) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) GeneralSecurityException(java.security.GeneralSecurityException) SigningKey(oidc.model.SigningKey) Assert.assertFalse(org.junit.Assert.assertFalse) ParseException(java.text.ParseException) SymmetricKey(oidc.model.SymmetricKey) Assert.assertEquals(org.junit.Assert.assertEquals) AbstractIntegrationTest(oidc.AbstractIntegrationTest) SeedUtils(oidc.SeedUtils) RefreshToken(oidc.model.RefreshToken) Query(org.springframework.data.mongodb.core.query.Query) AccessToken(oidc.model.AccessToken) SigningKey(oidc.model.SigningKey) Test(org.junit.Test) AbstractIntegrationTest(oidc.AbstractIntegrationTest)

Example 5 with AccessToken

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

the class AccessTokenRepositoryTest method findByValue.

@Test
public void findByValue() {
    String jwtId = UUID.randomUUID().toString();
    accessTokenRepository.insert(accessToken(jwtId, new Date()));
    AccessToken accessToken = accessTokenRepository.findByJwtId(jwtId).get();
    assertEquals(jwtId, accessToken.getJwtId());
}
Also used : AccessToken(oidc.model.AccessToken) Date(java.util.Date) Test(org.junit.Test) AbstractIntegrationTest(oidc.AbstractIntegrationTest)

Aggregations

AccessToken (oidc.model.AccessToken)8 SignedJWT (com.nimbusds.jwt.SignedJWT)4 RefreshToken (oidc.model.RefreshToken)4 HTTPRequest (com.nimbusds.oauth2.sdk.http.HTTPRequest)3 Date (java.util.Date)3 UnauthorizedException (oidc.exceptions.UnauthorizedException)3 User (oidc.model.User)3 ClientAuthentication (com.nimbusds.oauth2.sdk.auth.ClientAuthentication)2 PlainClientSecret (com.nimbusds.oauth2.sdk.auth.PlainClientSecret)2 IOException (java.io.IOException)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 Collectors.toList (java.util.stream.Collectors.toList)2 AbstractIntegrationTest (oidc.AbstractIntegrationTest)2 InvalidClientException (oidc.exceptions.InvalidClientException)2 InvalidGrantException (oidc.exceptions.InvalidGrantException)2 OpenIDClient (oidc.model.OpenIDClient)2 Test (org.junit.Test)2 ResponseEntity (org.springframework.http.ResponseEntity)2 JOSEException (com.nimbusds.jose.JOSEException)1