Search in sources :

Example 1 with JWTID

use of com.nimbusds.oauth2.sdk.id.JWTID 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 2 with JWTID

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

the class JWTRequestTest method plainJWT.

@Test(expected = UnsupportedJWTException.class)
public void plainJWT() throws Exception {
    OpenIDClient client = getClient();
    signedJWT(client.getClientId(), "keyID", client.getRedirectUrls().get(0));
    PlainJWT jwt = new PlainJWT(new JWTClaimsSet.Builder().jwtID(UUID.randomUUID().toString()).build());
    AuthenticationRequest authenticationRequest = new AuthenticationRequest.Builder(ResponseType.getDefault(), new Scope("openid"), new ClientID(client.getClientId()), new URI("http://localhost:8080")).requestObject(jwt).build();
    callParse(client, authenticationRequest);
}
Also used : PlainJWT(com.nimbusds.jwt.PlainJWT) Scope(com.nimbusds.oauth2.sdk.Scope) OpenIDClient(oidc.model.OpenIDClient) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) ClientID(com.nimbusds.oauth2.sdk.id.ClientID) AuthenticationRequest(com.nimbusds.openid.connect.sdk.AuthenticationRequest) URI(java.net.URI) Test(org.junit.Test)

Example 3 with JWTID

use of com.nimbusds.oauth2.sdk.id.JWTID in project di-authentication-api by alphagov.

the class UserInfoIntegrationTest method shouldCallUserInfoWithAccessTokenAndReturn200.

@Test
public void shouldCallUserInfoWithAccessTokenAndReturn200() throws JsonProcessingException {
    Subject internalSubject = new Subject();
    Subject publicSubject = new Subject();
    LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(10);
    Date expiryDate = Date.from(localDateTime.atZone(ZoneId.of("UTC")).toInstant());
    List<String> scopes = new ArrayList<>();
    scopes.add("email");
    scopes.add("phone");
    scopes.add("openid");
    JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim("scope", scopes).issuer("issuer-id").expirationTime(expiryDate).issueTime(Date.from(LocalDateTime.now().atZone(ZoneId.of("UTC")).toInstant())).claim("client_id", "client-id-one").subject(publicSubject.getValue()).jwtID(UUID.randomUUID().toString()).build();
    SignedJWT signedJWT = tokenSigner.signJwt(claimsSet);
    AccessToken accessToken = new BearerAccessToken(signedJWT.serialize());
    AccessTokenStore accessTokenStore = new AccessTokenStore(accessToken.getValue(), internalSubject.getValue());
    String accessTokenStoreString = new ObjectMapper().writeValueAsString(accessTokenStore);
    redis.addToRedis(ACCESS_TOKEN_PREFIX + CLIENT_ID + "." + publicSubject, accessTokenStoreString, 300L);
    setUpDynamo(internalSubject);
    var response = makeRequest(Optional.empty(), Map.of("Authorization", accessToken.toAuthorizationHeader()), Map.of());
    assertThat(response, hasStatus(200));
    UserInfo expectedUserInfoResponse = new UserInfo(publicSubject);
    expectedUserInfoResponse.setEmailAddress(TEST_EMAIL_ADDRESS);
    expectedUserInfoResponse.setEmailVerified(true);
    expectedUserInfoResponse.setPhoneNumber(FORMATTED_PHONE_NUMBER);
    expectedUserInfoResponse.setPhoneNumberVerified(true);
    assertThat(response.getBody(), equalTo(expectedUserInfoResponse.toJSONString()));
    assertNoAuditEventsReceived(auditTopic);
}
Also used : LocalDateTime(java.time.LocalDateTime) ArrayList(java.util.ArrayList) UserInfo(com.nimbusds.openid.connect.sdk.claims.UserInfo) SignedJWT(com.nimbusds.jwt.SignedJWT) Subject(com.nimbusds.oauth2.sdk.id.Subject) Date(java.util.Date) AccessTokenStore(uk.gov.di.authentication.shared.entity.AccessTokenStore) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Test(org.junit.jupiter.api.Test) ApiGatewayHandlerIntegrationTest(uk.gov.di.authentication.sharedtest.basetest.ApiGatewayHandlerIntegrationTest)

Example 4 with JWTID

use of com.nimbusds.oauth2.sdk.id.JWTID in project di-authentication-api by alphagov.

the class TokenService method generateAndStoreRefreshToken.

private RefreshToken generateAndStoreRefreshToken(String clientId, Subject internalSubject, List<String> scopes, Subject subject) {
    LOG.info("Generating RefreshToken");
    Date expiryDate = NowHelper.nowPlus(configService.getSessionExpiry(), ChronoUnit.SECONDS);
    var jwtId = IdGenerator.generate();
    JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim("scope", scopes).issuer(configService.getOidcApiBaseURL().get()).expirationTime(expiryDate).issueTime(NowHelper.now()).claim("client_id", clientId).subject(subject.getValue()).jwtID(jwtId).build();
    SignedJWT signedJWT = generateSignedJWT(claimsSet, Optional.empty());
    RefreshToken refreshToken = new RefreshToken(signedJWT.serialize());
    String redisKey = REFRESH_TOKEN_PREFIX + jwtId;
    var store = new RefreshTokenStore(refreshToken.getValue(), internalSubject.toString());
    try {
        redisConnectionService.saveWithExpiry(redisKey, objectMapper.writeValueAsString(store), configService.getSessionExpiry());
    } catch (JsonException e) {
        throw new RuntimeException("Error serializing refresh token store", e);
    }
    return refreshToken;
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) RefreshTokenStore(uk.gov.di.authentication.shared.entity.RefreshTokenStore) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) SignedJWT(com.nimbusds.jwt.SignedJWT) HashHelper.hashSha256String(uk.gov.di.authentication.shared.helpers.HashHelper.hashSha256String) Date(java.util.Date)

Example 5 with JWTID

use of com.nimbusds.oauth2.sdk.id.JWTID in project di-authentication-api by alphagov.

the class DocAppCriServiceTest method signJWTWithKMS.

private void signJWTWithKMS() throws JOSEException {
    var ecSigningKey = new ECKeyGenerator(Curve.P_256).keyID(KEY_ID).algorithm(JWSAlgorithm.ES256).generate();
    var claimsSet = new JWTAuthenticationClaimsSet(new ClientID(CLIENT_ID), singletonList(new Audience(buildURI(CRI_URI.toString(), "token"))), NowHelper.nowPlus(5, ChronoUnit.MINUTES), null, NowHelper.now(), new JWTID());
    var ecdsaSigner = new ECDSASigner(ecSigningKey);
    var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES256).keyID(ecSigningKey.getKeyID()).build();
    var signedJWT = new SignedJWT(jwsHeader, claimsSet.toJWTClaimsSet());
    unchecked(signedJWT::sign).accept(ecdsaSigner);
    var signResult = new SignResult();
    byte[] idTokenSignatureDer = ECDSA.transcodeSignatureToDER(signedJWT.getSignature().decode());
    signResult.setSignature(ByteBuffer.wrap(idTokenSignatureDer));
    signResult.setKeyId(KEY_ID);
    signResult.setSigningAlgorithm(JWSAlgorithm.ES256.getName());
    when(kmsService.sign(any(SignRequest.class))).thenReturn(signResult);
}
Also used : SignResult(com.amazonaws.services.kms.model.SignResult) SignRequest(com.amazonaws.services.kms.model.SignRequest) Audience(com.nimbusds.oauth2.sdk.id.Audience) ECDSASigner(com.nimbusds.jose.crypto.ECDSASigner) ECKeyGenerator(com.nimbusds.jose.jwk.gen.ECKeyGenerator) ClientID(com.nimbusds.oauth2.sdk.id.ClientID) JWTID(com.nimbusds.oauth2.sdk.id.JWTID) JWTAuthenticationClaimsSet(com.nimbusds.oauth2.sdk.auth.JWTAuthenticationClaimsSet) SignedJWT(com.nimbusds.jwt.SignedJWT)

Aggregations

SignedJWT (com.nimbusds.jwt.SignedJWT)9 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)6 ClientID (com.nimbusds.oauth2.sdk.id.ClientID)5 JWTAuthenticationClaimsSet (com.nimbusds.oauth2.sdk.auth.JWTAuthenticationClaimsSet)4 Audience (com.nimbusds.oauth2.sdk.id.Audience)4 JWTID (com.nimbusds.oauth2.sdk.id.JWTID)4 AccessToken (com.nimbusds.oauth2.sdk.token.AccessToken)4 BearerAccessToken (com.nimbusds.oauth2.sdk.token.BearerAccessToken)4 Date (java.util.Date)4 AccessTokenStore (uk.gov.di.authentication.shared.entity.AccessTokenStore)4 Test (org.junit.jupiter.api.Test)3 ApiGatewayHandlerIntegrationTest (uk.gov.di.authentication.sharedtest.basetest.ApiGatewayHandlerIntegrationTest)3 SignRequest (com.amazonaws.services.kms.model.SignRequest)2 SignResult (com.amazonaws.services.kms.model.SignResult)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)2 ECDSASigner (com.nimbusds.jose.crypto.ECDSASigner)2 ECKeyGenerator (com.nimbusds.jose.jwk.gen.ECKeyGenerator)2 AuthorizationCode (com.nimbusds.oauth2.sdk.AuthorizationCode)2 AuthorizationCodeGrant (com.nimbusds.oauth2.sdk.AuthorizationCodeGrant)2 TokenRequest (com.nimbusds.oauth2.sdk.TokenRequest)2