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();
}
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;
}
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);
}
}
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;
}
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;
}
Aggregations