3
votes

I'm using actionable messages (with Outlook web app) to call an Logic App. Therefore I am getting an Bearer token in the request:

"Action-Authorization": "Bearer eyJ0eXAi..."

Callstack: Outlook web app -> Logic App -> my endpoint hosted in azure

Now I tried to validate the token with jwt.io but getting an Issue that the Signature is invalid. So I tried to validate it in c# with the JwtSecurityTokenHandler.

I tried to add https://substrate.office.com/sts/ to the issuer list, but it seems like the validation don't even get there.

I'm using the following code to validate the jwt token issued by office.com:

bool IsAuthorized(HttpActionContext actionContext)
        {
            var valid = base.IsAuthorized(actionContext);

            // Custom handle for Bearer token, when invalid from base-class
            if (!valid && actionContext.Request.Headers.Authorization.Scheme == "Bearer")
            {
                var jwt = actionContext.Request.Headers.Authorization.Parameter;
                var th = new JwtSecurityTokenHandler();
                var sjwt = th.ReadToken(jwt) as JwtSecurityToken;                

                var validationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = false,
                    //IssuerSigningToken = sjwt,
                    ValidateActor = false,
                    ValidateAudience = false,
                    ValidateIssuer = true,
                    ValidateLifetime = true,
                    ValidIssuers = new[] { "https://substrate.office.com/sts/" },
                    ValidAudiences = new[] {"https://XXX.logic.azure.com"}
        };

                SecurityToken validatedToken;
                try
                {
                    th.ValidateToken(jwt, validationParameters, out validatedToken);
                }
                catch (Exception ex)
                {
                    return false;
                }
            }

            return valid;
        }

Here is my JWT token:

JWT Token

I am getting the exception:

IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier: 'SecurityKeyIdentifier
    (
    IsReadOnly = False,
    Count = 2,
    Clause[0] = X509ThumbprintKeyIdentifierClause(Hash = 0x818...),
    Clause[1] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause
    )
', ...

Even though I set ValidateIssuerSigningKey = false.

Is there a way to accept https://substrate.office.com/sts/ as a valid issuer?

1
Could you show us what does your token look like ? the issuer should be the value in the "iss" claimThomas
Also the ValidateIssuerSigningKey has a different purpose. It is here to validate that the token has been issued by the right\wanted authorization server. You should not set this property to falseThomas
I added the token. ValidateIssuerSigningKey=false is only for testing purpose, i thought this would mitigate the exception I get.Celdus

1 Answers

1
votes

The exception says that the "Signature validation failed". To resolve this problem we can't just add the wanted valid issuer to ValidIssuers, we need the to verify that the token is issued from the issuer itself.

Especially for this case with office.com being the issuer I found the expected key (JWK - JSON Web Key) here: https://substrate.office.com/sts/common/discovery/keys (also https://substrate.office.com/sts/common/.well-known/openid-configuration)

Here is the working code:

bool IsAuthorized(HttpActionContext actionContext)
        {
            var valid = base.IsAuthorized(actionContext);

            // Custom handle for Bearer token, when invalid from base-class
            if (!valid && actionContext.Request.Headers.Authorization.Scheme == "Bearer")
            {
                var jwt = actionContext.Request.Headers.Authorization.Parameter;
                var th = new JwtSecurityTokenHandler();

                var validationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false,
                    ValidateLifetime = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new JsonWebKey(GetJWK()),
                    ValidIssuers = new[] { "https://substrate.office.com/sts/" }
                };

                Microsoft.IdentityModel.Tokens.SecurityToken validatedToken;
                try
                {
                    var claims = th.ValidateToken(jwt, validationParameters, out validatedToken);
                    valid = true;
                }
                catch (Exception ex)
                {
                    valid = false;
                }
            }

            return valid;
        }

        // Get the token from configuration
        private string GetJWK()
        {
            return ConfigurationManager.AppSettings["ida:jwks_json"];
        }

In the appsettings I put the RSA key from the website for validating the token, it looks like:

{"kty":"RSA","use":"sig","kid":"gY...","x5t":"gY...","n":"2w...","e":"AQAB","x5c":["MII..."]}