Search in sources :

Example 1 with AuthnRequest

use of it.spid.cie.oidc.model.AuthnRequest 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 AuthnRequest

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

the class SpidController method logout.

@GetMapping("/logout")
public RedirectView logout(@RequestParam Map<String, String> params, final HttpServletRequest request, HttpServletResponse response) throws Exception {
    String userKey = GetterUtil.getString(request.getSession().getAttribute("USER"));
    String redirectURL = relyingPartyWrapper.performLogout(userKey, new RelyingPartyLogoutCallback() {

        @Override
        public void logout(String userKey, AuthnRequest authnRequest, AuthnToken authnToken) {
            request.getSession().removeAttribute("USER");
            request.getSession().removeAttribute("USER_INFO");
        }
    });
    if (!Validator.isNullOrEmpty(redirectURL)) {
        return new RedirectView(redirectURL);
    }
    return new RedirectView("landing");
}
Also used : RelyingPartyLogoutCallback(it.spid.cie.oidc.callback.RelyingPartyLogoutCallback) AuthnRequest(it.spid.cie.oidc.model.AuthnRequest) AuthnToken(it.spid.cie.oidc.model.AuthnToken) RedirectView(org.springframework.web.servlet.view.RedirectView) GetMapping(org.springframework.web.bind.annotation.GetMapping)

Example 3 with AuthnRequest

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

the class AuthnRequestModel method toAuthnRequest.

public AuthnRequest toAuthnRequest() {
    AuthnRequest target = new AuthnRequest();
    target.setStorageId(getStorageId());
    target.setCreateDate(getCreated());
    target.setModifiedDate(getModified());
    target.setClientId(getClientId());
    target.setData(getData());
    target.setEndpoint(getEndpoint());
    target.setProvider(getProvider());
    target.setProviderConfiguration(getProviderConfiguration());
    target.setProviderId(getProviderId());
    target.setProviderJwks(getProviderJwks());
    target.setState(getState());
    target.setSuccessful(isSuccessful());
    return target;
}
Also used : AuthnRequest(it.spid.cie.oidc.model.AuthnRequest)

Example 4 with AuthnRequest

use of it.spid.cie.oidc.model.AuthnRequest 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 AuthnRequest

use of it.spid.cie.oidc.model.AuthnRequest 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

AuthnRequest (it.spid.cie.oidc.model.AuthnRequest)5 JWKSet (com.nimbusds.jose.jwk.JWKSet)3 OIDCException (it.spid.cie.oidc.exception.OIDCException)3 RelyingPartyException (it.spid.cie.oidc.exception.RelyingPartyException)3 SchemaException (it.spid.cie.oidc.exception.SchemaException)3 TrustChainException (it.spid.cie.oidc.exception.TrustChainException)3 AuthnToken (it.spid.cie.oidc.model.AuthnToken)3 FederationEntity (it.spid.cie.oidc.model.FederationEntity)3 JSONObject (org.json.JSONObject)3 RelyingPartyLogoutCallback (it.spid.cie.oidc.callback.RelyingPartyLogoutCallback)1 TrustChain (it.spid.cie.oidc.model.TrustChain)1 TokenResponse (it.spid.cie.oidc.schemas.TokenResponse)1 JSONArray (org.json.JSONArray)1 GetMapping (org.springframework.web.bind.annotation.GetMapping)1 RedirectView (org.springframework.web.servlet.view.RedirectView)1