Search in sources :

Example 1 with FederationEntity

use of it.spid.cie.oidc.model.FederationEntity in project spid-cie-oidc-java by italia.

the class RelyingPartyHandler method doPerformLogout.

protected String doPerformLogout(String userKey, RelyingPartyLogoutCallback callback) throws Exception {
    if (Validator.isNullOrEmpty(userKey)) {
        throw new RelyingPartyException.Generic("UserKey null or empty");
    }
    List<AuthnToken> authnTokens = persistence.findAuthnTokens(userKey);
    if (authnTokens.isEmpty()) {
        return options.getLogoutRedirectURL();
    }
    AuthnToken authnToken = ListUtil.getLast(authnTokens);
    AuthnRequest authnRequest = persistence.fetchAuthnRequest(authnToken.getAuthnRequestId());
    if (authnRequest == null) {
        throw new RelyingPartyException.Generic("No AuthnRequest with id " + authnToken.getAuthnRequestId());
    }
    JSONObject providerConfiguration = new JSONObject(authnRequest.getProviderConfiguration());
    String revocationUrl = providerConfiguration.optString("revocation_endpoint");
    if (callback != null) {
        callback.logout(userKey, authnRequest, authnToken);
    }
    if (Validator.isNullOrEmpty(revocationUrl)) {
        logger.warn("{} doesn't expose the token revocation endpoint.", authnRequest.getProviderId());
        return options.getLogoutRedirectURL();
    }
    FederationEntity entityConf = persistence.fetchFederationEntity(authnRequest.getClientId(), true);
    JWKSet jwkSet = JWTHelper.getJWKSetFromJSON(entityConf.getJwks());
    authnToken.setRevoked(LocalDateTime.now());
    authnToken = persistence.storeOIDCAuthnToken(authnToken);
    try {
        oauth2Helper.sendRevocationRequest(authnToken.getAccessToken(), authnRequest.getClientId(), revocationUrl, entityConf);
    } catch (Exception e) {
        logger.error("Token revocation failed: {}", e.getMessage());
    }
    // Revoke older user's authnToken. Evaluate better
    authnTokens = persistence.findAuthnTokens(userKey);
    for (AuthnToken oldToken : authnTokens) {
        oldToken.setRevoked(authnToken.getRevoked());
        persistence.storeOIDCAuthnToken(oldToken);
    }
    return options.getLogoutRedirectURL();
}
Also used : FederationEntity(it.spid.cie.oidc.model.FederationEntity) AuthnRequest(it.spid.cie.oidc.model.AuthnRequest) JSONObject(org.json.JSONObject) AuthnToken(it.spid.cie.oidc.model.AuthnToken) JWKSet(com.nimbusds.jose.jwk.JWKSet) SchemaException(it.spid.cie.oidc.exception.SchemaException) OIDCException(it.spid.cie.oidc.exception.OIDCException) RelyingPartyException(it.spid.cie.oidc.exception.RelyingPartyException) TrustChainException(it.spid.cie.oidc.exception.TrustChainException)

Example 2 with FederationEntity

use of it.spid.cie.oidc.model.FederationEntity in project spid-cie-oidc-java by italia.

the class FederationEntityModel method toFederationEntity.

public FederationEntity toFederationEntity() {
    FederationEntity target = new FederationEntity();
    target.setStorageId(getStorageId());
    target.setCreateDate(getCreated());
    target.setModifiedDate(getModified());
    target.setSubject(getSub());
    target.setDefaultExpireMinutes(getDefaultExpireMinutes());
    target.setDefaultSignatureAlg(getDefaultSignatureAlg());
    target.setEntityType(getEntityType());
    target.setActive(isActive());
    target.setAuthorityHints(getAuthorityHints());
    target.setConstraints(getConstraints());
    target.setJwks(getJwks());
    target.setTrustMarks(getTrustMarks());
    target.setTrustMarksIssuers(getTrustMarksIssuers());
    target.setMetadata(getMetadata());
    return target;
}
Also used : FederationEntity(it.spid.cie.oidc.model.FederationEntity)

Example 3 with FederationEntity

use of it.spid.cie.oidc.model.FederationEntity in project spid-cie-oidc-java by italia.

the class RelyingPartyHandler method getWellKnownData.

/**
 * Return the "Well Known" information of the current Relying Party. The completeness
 * of these informations depends of the federation on-boarding status of the entity.
 *
 * @param requestURL
 * @param jsonMode
 * @return
 * @throws OIDCException
 */
public WellKnownData getWellKnownData(String requestURL, boolean jsonMode) throws OIDCException {
    String sub = getSubjectFromURL(requestURL);
    if (!Objects.equals(sub, options.getClientId())) {
        throw new OIDCException(String.format("Sub doesn't match %s : %s", sub, options.getClientId()));
    }
    FederationEntity conf = persistence.fetchFederationEntity(sub, true);
    if (conf == null) {
        return prepareOnboardingData(sub, jsonMode);
    } else {
        return getWellKnownData(conf, jsonMode);
    }
}
Also used : FederationEntity(it.spid.cie.oidc.model.FederationEntity) OIDCException(it.spid.cie.oidc.exception.OIDCException)

Example 4 with FederationEntity

use of it.spid.cie.oidc.model.FederationEntity in project spid-cie-oidc-java by italia.

the class RelyingPartyHandler method getAuthorizeURL.

/**
 * Build the "authorize url": the URL a RelyingParty have to send to an OpenID
 * Provider to start a SPID authorization flow
 *
 * @param spidProvider
 * @param trustAnchor
 * @param redirectUri
 * @param scope
 * @param profile
 * @param prompt
 * @return
 * @throws OIDCException
 */
public String getAuthorizeURL(String spidProvider, String trustAnchor, String redirectUri, String scope, String profile, String prompt) throws OIDCException {
    // TODO: CIE could reuse this flow?
    if (Validator.isNullOrEmpty(profile)) {
        profile = OIDCProfile.SPID.getValue();
    }
    TrustChain tc = getSPIDProvider(spidProvider, trustAnchor);
    if (tc == null) {
        throw new OIDCException("TrustChain is unavailable");
    }
    JSONObject providerMetadata;
    try {
        providerMetadata = new JSONObject(tc.getMetadata());
        if (providerMetadata.isEmpty()) {
            throw new OIDCException("Provider metadata is empty");
        }
    } catch (Exception e) {
        throw e;
    }
    FederationEntity entityConf = persistence.fetchFederationEntity(OIDCConstants.OPENID_RELYING_PARTY);
    if (entityConf == null || !entityConf.isActive()) {
        throw new OIDCException("Missing configuration");
    }
    JSONObject entityMetadata;
    JWKSet entityJWKSet;
    try {
        entityMetadata = entityConf.getMetadataValue(OIDCConstants.OPENID_RELYING_PARTY);
        if (entityMetadata.isEmpty()) {
            throw new OIDCException("Entity metadata is empty");
        }
        entityJWKSet = JWTHelper.getJWKSetFromJSON(entityConf.getJwks());
        if (entityJWKSet.getKeys().isEmpty()) {
            throw new OIDCException("Entity with invalid or empty jwks");
        }
    } catch (OIDCException e) {
        throw e;
    }
    JWKSet providerJWKSet = JWTHelper.getMetadataJWKSet(providerMetadata);
    String authzEndpoint = providerMetadata.getString("authorization_endpoint");
    JSONArray entityRedirectUris = entityMetadata.getJSONArray("redirect_uris");
    if (entityRedirectUris.isEmpty()) {
        throw new OIDCException("Entity has no redirect_uris");
    }
    if (!Validator.isNullOrEmpty(redirectUri)) {
        if (!JSONUtil.contains(entityRedirectUris, redirectUri)) {
            logger.warn("Requested for unknown redirect uri '{}'. Reverted to default '{}'", redirectUri, entityRedirectUris.getString(0));
            redirectUri = entityRedirectUris.getString(0);
        }
    } else {
        redirectUri = entityRedirectUris.getString(0);
    }
    if (Validator.isNullOrEmpty(scope)) {
        scope = OIDCConstants.SCOPE_OPENID;
    }
    if (Validator.isNullOrEmpty(profile)) {
        profile = options.getAcrValue(OIDCProfile.SPID);
    }
    if (Validator.isNullOrEmpty(prompt)) {
        prompt = "consent login";
    }
    String responseType = entityMetadata.getJSONArray("response_types").getString(0);
    String nonce = UUID.randomUUID().toString();
    String state = UUID.randomUUID().toString();
    String clientId = entityMetadata.getString("client_id");
    long issuedAt = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
    String[] aud = new String[] { tc.getSubject(), authzEndpoint };
    JSONObject claims = getRequestedClaims(profile);
    JSONObject pkce = PKCEHelper.getPKCE();
    String acr = options.getAcrValue(OIDCProfile.SPID);
    JSONObject authzData = new JSONObject().put("scope", scope).put("redirect_uri", redirectUri).put("response_type", responseType).put("nonce", nonce).put("state", state).put("client_id", clientId).put("endpoint", authzEndpoint).put("acr_values", acr).put("iat", issuedAt).put("aud", JSONUtil.asJSONArray(aud)).put("claims", claims).put("prompt", prompt).put("code_verifier", pkce.getString("code_verifier")).put("code_challenge", pkce.getString("code_challenge")).put("code_challenge_method", pkce.getString("code_challenge_method"));
    AuthnRequest authzEntry = new AuthnRequest().setClientId(clientId).setState(state).setEndpoint(authzEndpoint).setProvider(tc.getSubject()).setProviderId(tc.getSubject()).setData(authzData.toString()).setProviderJwks(providerJWKSet.toString()).setProviderConfiguration(providerMetadata.toString());
    authzEntry = persistence.storeOIDCAuthnRequest(authzEntry);
    authzData.remove("code_verifier");
    authzData.put("iss", entityMetadata.getString("client_id"));
    authzData.put("sub", entityMetadata.getString("client_id"));
    String requestObj = jwtHelper.createJWS(authzData, entityJWKSet);
    authzData.put("request", requestObj);
    String url = buildURL(authzEndpoint, authzData);
    logger.info("Starting Authn request to {}", url);
    return url;
}
Also used : FederationEntity(it.spid.cie.oidc.model.FederationEntity) TrustChain(it.spid.cie.oidc.model.TrustChain) JSONObject(org.json.JSONObject) AuthnRequest(it.spid.cie.oidc.model.AuthnRequest) OIDCException(it.spid.cie.oidc.exception.OIDCException) JWKSet(com.nimbusds.jose.jwk.JWKSet) JSONArray(org.json.JSONArray) SchemaException(it.spid.cie.oidc.exception.SchemaException) OIDCException(it.spid.cie.oidc.exception.OIDCException) RelyingPartyException(it.spid.cie.oidc.exception.RelyingPartyException) TrustChainException(it.spid.cie.oidc.exception.TrustChainException)

Example 5 with FederationEntity

use of it.spid.cie.oidc.model.FederationEntity in project spid-cie-oidc-java by italia.

the class RelyingPartyHandler method doGetUserInfo.

protected JSONObject doGetUserInfo(String state, String code) throws OIDCException {
    if (Validator.isNullOrEmpty(code) || Validator.isNullOrEmpty(state)) {
        throw new SchemaException.Validation("Authn response object validation failed");
    }
    List<AuthnRequest> authnRequests = persistence.findAuthnRequests(state);
    if (authnRequests.isEmpty()) {
        throw new RelyingPartyException.Generic("No AuthnRequest");
    }
    AuthnRequest authnRequest = ListUtil.getLast(authnRequests);
    AuthnToken authnToken = new AuthnToken().setAuthnRequestId(authnRequest.getStorageId()).setCode(code);
    authnToken = persistence.storeOIDCAuthnToken(authnToken);
    // Get clientId configuration. In this situation "clientId" refers this
    // RelyingParty
    FederationEntity entityConf = persistence.fetchFederationEntity(authnRequest.getClientId(), true);
    if (entityConf == null) {
        throw new RelyingPartyException.Generic("RelyingParty %s not found", authnRequest.getClientId());
    } else if (!Objects.equals(options.getClientId(), authnRequest.getClientId())) {
        throw new RelyingPartyException.Generic("Invalid RelyingParty %s", authnRequest.getClientId());
    }
    JSONObject authnData = new JSONObject(authnRequest.getData());
    JSONObject providerConfiguration = new JSONObject(authnRequest.getProviderConfiguration());
    JSONObject jsonTokenResponse = oauth2Helper.performAccessTokenRequest(authnData.optString("redirect_uri"), state, code, authnRequest.getProviderId(), entityConf, providerConfiguration.optString("token_endpoint"), authnData.optString("code_verifier"));
    TokenResponse tokenResponse = TokenResponse.of(jsonTokenResponse);
    if (logger.isDebugEnabled()) {
        logger.debug("TokenResponse=" + tokenResponse.toString());
    }
    JWKSet providerJwks = JWTHelper.getJWKSetFromJSON(providerConfiguration.optJSONObject("jwks"));
    try {
        jwtHelper.verifyJWS(tokenResponse.getAccessToken(), providerJwks);
    } catch (Exception e) {
        throw new RelyingPartyException.Authentication("Authentication token validation error.");
    }
    try {
        jwtHelper.verifyJWS(tokenResponse.getIdToken(), providerJwks);
    } catch (Exception e) {
        throw new RelyingPartyException.Authentication("ID token validation error.");
    }
    // Update AuthenticationToken
    authnToken.setAccessToken(tokenResponse.getAccessToken());
    authnToken.setIdToken(tokenResponse.getIdToken());
    authnToken.setTokenType(tokenResponse.getTokenType());
    authnToken.setScope(jsonTokenResponse.optString("scope"));
    authnToken.setExpiresIn(tokenResponse.getExpiresIn());
    authnToken = persistence.storeOIDCAuthnToken(authnToken);
    JWKSet entityJwks = JWTHelper.getJWKSetFromJSON(entityConf.getJwks());
    JSONObject userInfo = oidcHelper.getUserInfo(state, tokenResponse.getAccessToken(), providerConfiguration, true, entityJwks);
    // TODO: userKey from options
    authnToken.setUserKey(userInfo.optString("https://attributes.spid.gov.it/email"));
    authnToken = persistence.storeOIDCAuthnToken(authnToken);
    return userInfo;
}
Also used : SchemaException(it.spid.cie.oidc.exception.SchemaException) OIDCException(it.spid.cie.oidc.exception.OIDCException) RelyingPartyException(it.spid.cie.oidc.exception.RelyingPartyException) TrustChainException(it.spid.cie.oidc.exception.TrustChainException) FederationEntity(it.spid.cie.oidc.model.FederationEntity) AuthnRequest(it.spid.cie.oidc.model.AuthnRequest) JSONObject(org.json.JSONObject) TokenResponse(it.spid.cie.oidc.schemas.TokenResponse) AuthnToken(it.spid.cie.oidc.model.AuthnToken) JWKSet(com.nimbusds.jose.jwk.JWKSet) RelyingPartyException(it.spid.cie.oidc.exception.RelyingPartyException)

Aggregations

FederationEntity (it.spid.cie.oidc.model.FederationEntity)6 JWKSet (com.nimbusds.jose.jwk.JWKSet)4 OIDCException (it.spid.cie.oidc.exception.OIDCException)4 JSONObject (org.json.JSONObject)4 RelyingPartyException (it.spid.cie.oidc.exception.RelyingPartyException)3 SchemaException (it.spid.cie.oidc.exception.SchemaException)3 TrustChainException (it.spid.cie.oidc.exception.TrustChainException)3 AuthnRequest (it.spid.cie.oidc.model.AuthnRequest)3 AuthnToken (it.spid.cie.oidc.model.AuthnToken)2 JSONArray (org.json.JSONArray)2 RSAKey (com.nimbusds.jose.jwk.RSAKey)1 TrustChain (it.spid.cie.oidc.model.TrustChain)1 TokenResponse (it.spid.cie.oidc.schemas.TokenResponse)1