/// <summary> /// 2) Dopo che Identity Server ha autorizzato redirige il browser verso il servizio Auth di ARXivar con code + id_token /// Viene preparato il contesto autorizzativo che avverrà utilizzato nel metodo Authorize /// </summary> /// <param name="receiveTokenRequest"></param> /// <returns></returns> /// <exception cref="SecurityException"></exception> public override OpenIdReceiveTokenResponse ReceiveToken(OpenIdReceiveTokenRequest receiveTokenRequest) { OpenIdReceiveTokenResponse response = new OpenIdReceiveTokenResponse { SessionState = receiveTokenRequest.SessionState, }; try { Logger.Debug("OpenID Logon Provider ReceiveToken"); var code = receiveTokenRequest.Code; var idToken = receiveTokenRequest.IdToken; // Recupero parametri logon provider var logonProviderConfiguration = GetProviderConfiguration(); var identityServerKeysDiscoveryUrl = logonProviderConfiguration.FirstOrDefault(x => x.Name.Equals(IdentityServerKeysDiscoveryUrlParam))?.Value as string; if (string.IsNullOrWhiteSpace(identityServerKeysDiscoveryUrl)) { throw new System.Security.SecurityException(string.Format("Wrong logon provider configuration parameter: {0}", IdentityServerKeysDiscoveryUrlParam)); } // Decodifico il token JWT var handler = new JwtSecurityTokenHandler(); var jsonToken = handler.ReadToken(idToken) as JwtSecurityToken; if (jsonToken == null) { throw new SecurityException("idToken is not a JWT token (null cast)"); } if (jsonToken.ValidFrom > DateTime.UtcNow) { throw new SecurityException(string.Format("JWT Token is not valid yet: {0}", jsonToken.ValidFrom.ToString("O"))); } if (jsonToken.ValidTo < DateTime.UtcNow) { throw new SecurityException(string.Format("Expired JWT Token: {0}", jsonToken.ValidTo.ToString("O"))); } // Verifica ClientId dell'applicazione var clientId = jsonToken.Payload.Aud.FirstOrDefault(); if (string.IsNullOrWhiteSpace(clientId)) { throw new SecurityException(string.Format("Unable to determine the claim: {0}", "ClientId (aud)")); } // Email var email = jsonToken.Payload.Claims.FirstOrDefault(x => x.Type.Equals(TokenClaims.Email))?.Value; if (string.IsNullOrWhiteSpace(email)) { throw new SecurityException(string.Format("Unable to determine the claim: {0}", TokenClaims.Email)); } // PreferredUsername var preferreduserName = jsonToken.Payload.Claims.FirstOrDefault(x => x.Type.Equals(TokenClaims.PreferredUsername))?.Value; if (string.IsNullOrWhiteSpace(email)) { throw new SecurityException(string.Format("Unable to determine the claim: {0}", TokenClaims.PreferredUsername)); } // User name var userName = jsonToken.Payload.Claims.FirstOrDefault(x => x.Type.Equals(TokenClaims.Name))?.Value; if (string.IsNullOrWhiteSpace(email)) { throw new SecurityException(string.Format("Unable to determine the claim: {0}", TokenClaims.Name)); } // Issuer var issuer = jsonToken.Payload.Claims.FirstOrDefault(x => x.Type.Equals(TokenClaims.Issuer))?.Value; if (string.IsNullOrWhiteSpace(email)) { throw new SecurityException(string.Format("Unable to determine the claim: {0}", TokenClaims.Issuer)); } Logger.InfoFormat("OpenID Username: {0} Email: {1} ClientId: {2} Issuer: {3} Code: {4}", email, userName, clientId, issuer, code); // Recupero la chiave utilizzata per firmare il token JWT if (!jsonToken.Header.Typ.Equals("JWT")) { throw new SecurityException(string.Format("Token Type is not JWT: {0}", jsonToken.Header.Typ)); } if (!jsonToken.Header.Alg.Equals("RS256")) { throw new SecurityException(string.Format("Token algorithm not handled: {0}", jsonToken.Header.Alg)); } var keyId = jsonToken.Header.Kid; if (string.IsNullOrWhiteSpace(keyId)) { throw new SecurityException("Unable to determine the signing key"); } // Verifico che la firma digitale del token JWT sia coerente con la chiave pubblica RSA pubblicata Logger.DebugFormat("Verify JWT signature: {0} ...", identityServerKeysDiscoveryUrl); TokenJwtHelper.VerifyTokenJwtSignature(jsonToken, identityServerKeysDiscoveryUrl, Logger); Logger.DebugFormat("JWT signature OK"); // Inserisco la lista dei parametri del giro code in session state protetto lato server response.SessionState.Add(new KeyValuePair <string, string>(TokenClaims.Code, code)); response.SessionState.Add(new KeyValuePair <string, string>(TokenClaims.Issuer, issuer)); response.SessionState.Add(new KeyValuePair <string, string>(TokenClaims.ClientId, clientId)); response.SessionState.Add(new KeyValuePair <string, string>(TokenClaims.Email, email)); response.SessionState.Add(new KeyValuePair <string, string>(TokenClaims.PreferredUsername, preferreduserName)); } catch (Exception e) { Logger.Error(e); response.Error = new OpenIdError { ErrorCode = e.GetType().FullName, ErrorDescription = e.ToString() }; } return(response); }
internal static void VerifyTokenJwtSignature(JwtSecurityToken tokenJwt, string pkiUri, ILog logger) { TokenKeys tokenKeys; try { TokenKey signingKey = null; string responseAsString; using (var hc = new HttpClient()) { HttpResponseMessage responseContent; try { logger.DebugFormat("Sign key loading from: {0}", pkiUri); responseContent = hc.GetAsync(pkiUri).Result; } catch (Exception e) { var errorMessage = string.Format("Verify JWT token error calling {0} -> ", pkiUri) + e.Message; logger.Error(errorMessage); throw new HttpException(errorMessage); } if (!responseContent.IsSuccessStatusCode) { throw new SecurityException(pkiUri + " error code: " + responseContent.StatusCode.ToString()); } responseAsString = responseContent.Content.ReadAsStringAsync().Result; } tokenKeys = JsonConvert.DeserializeObject <TokenKeys>(responseAsString); if (tokenKeys.TokenKeyList != null) { signingKey = tokenKeys?.TokenKeyList.FirstOrDefault(x => x.KeyId.Equals(tokenJwt.Header.Kid)); logger.DebugFormat("Sign key found: {0}", signingKey.KeyId); } if (signingKey == null) { // Chiave non trovata! throw new SecurityException("Token sign key not found: " + tokenJwt.Header.Kid); } if (!signingKey.KeyType.Equals("RSA")) { throw new SecurityException("Token sign key is not RSA: " + signingKey.KeyType); } if (!signingKey.Use.Equals("sig")) { throw new SecurityException("Token sign key use is not sig: " + signingKey.Use); } var jwtSignatureValid = TokenJwtHelper.VerifyTokenJwtSignatureInternal(tokenJwt.RawData, signingKey.Modolus, signingKey.PublicExponent); if (!jwtSignatureValid) { throw new SecurityException("Token JWT signature is not valid, kid: " + signingKey.KeyId); } } catch (Exception e) { logger.Error("VerifyTokenJwtSignature error", e); throw; } }