/// <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);
        }
Пример #2
0
        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;
            }
        }