4

I am trying to verify a json web token obtained by a firebase android client and passed to a server running .net

Following the answer here I created these methods to validate the token and extract the uid:

public static async Task<string> GetUserNameFromTokenIfValid(string jsonWebToken)
    {
        const string FirebaseProjectId = "testapp-16ecd";
        try
        {
            // 1. Get Google signing keys
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("https://www.googleapis.com/robot/v1/metadata/");
            HttpResponseMessage response = await client.GetAsync("x509/[email protected]");
            if (!response.IsSuccessStatusCode) { return null; }
            var x509Data = await response.Content.ReadAsAsync<Dictionary<string, string>>();
            SecurityKey[] keys = x509Data.Values.Select(CreateSecurityKeyFromPublicKey).ToArray();

            // Use JwtSecurityTokenHandler to validate the JWT token
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

            // Set the expected properties of the JWT token in the TokenValidationParameters
            TokenValidationParameters validationParameters = new TokenValidationParameters()
            {
                ValidAudience = FirebaseProjectId,
                ValidIssuer = "https://securetoken.google.com/" + FirebaseProjectId,
                ValidateIssuerSigningKey = true,
                IssuerSigningKeys = keys
            };
            SecurityToken validatedToken;
            ClaimsPrincipal principal = tokenHandler.ValidateToken(jsonWebToken, validationParameters, out validatedToken);
            var jwt = (JwtSecurityToken)validatedToken;
            return jwt.Subject;

        }
        catch (Exception e)
        {
            return null;
        }
    }

    static SecurityKey CreateSecurityKeyFromPublicKey(string data)
    {
        return new X509SecurityKey(new X509Certificate2(Encoding.UTF8.GetBytes(data)));
    }

When I run the code I get the response:

{"IDX10501: Signature validation failed. Unable to match 'kid': 'c2154b0435d58fc96a4480bd7655188fd4370b07', \ntoken: '{"alg":"RS256","typ":"JWT","kid":"c2154b0435d58fc96a4480bd7655188fd4370b07"}......

Calling https://www.googleapis.com/robot/v1/metadata/x509/[email protected] does return a certificate with a matching id:

{
 "c2154b0435d58fc96a4480bd7655188fd4370b07": "-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIIRZGQCmoKoNQwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE\nAxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMTYx\nMTIxMDA0NTI2WhcNMTYxMTI0MDExNTI2WjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl\nbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAKHbxqFaNQyrrrv8gocpQjES+HCum8XRQYYLRqstJ12FGtDN\np32qagCbc0x94TaBZF7tCPMgyFU8pBQP7CvCxWxoy+Xdv+52lcR0sG/kskr23E3N\nJmWVHT3YwiMwdgsbWDIpWEbvJdn3DPFaapvD9BJPwNoXuFCO2vA2rhi1LuNWsaHt\nBj5jTicGCnt2PGKUTXJ9q1hOFi90wxTVUVMfFqDa4g9iKqRoaNaLOo0w3VgsFPlr\nMBca1fw1ArZpEGm3XHaDOiCi+EZ2+GRvdF/aPNy1+RdnUPMEEuHErULSxXpYGIdt\n/Mo7QvtFXkIl6ZHvEp5pWkS8mlAJyfPrOs8RzXMCAwEAAaM4MDYwDAYDVR0TAQH/\nBAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ\nKoZIhvcNAQEFBQADggEBAJYXDQFIOC0W0ZwLO/5afSlqtMZ+lSiFJJnGx/IXI5Mi\n0sBI3QA7QXmiNH4tVyEiK+HsFPKAYovsbh7HDypEnBGsz9UmEU6Wn6Qu9/v38+bo\nLant6Ds9ME7QHhKJKtYkso0F2RVwu220xZQl1yrl4bjq+2ZDncYthILjw5t+8Z4c\nQW5UCr2wlVtkflGtIPR1UrvyU13eiI5SPkwOWPZvG2iTabnLfcRIkhQgIalkznMe\niz8Pzpk9eT8HFeZYiB61GpIWHG4oEb1/Z4Q//os+vWDQ+X0ARTYhTEbwLLQ0dcjW\nfg/tm7J+MGH5NH5MwjO+CI4fA3NoGOuEzF1vb7/hNdU=\n-----END CERTIFICATE-----\n"

I have successfully validated this token using the Java call (made in kotlin)

FirebaseAuth.getInstance().verifyIdToken(idToken).addOnSuccessListener { decodedToken ->
    val uid = decodedToken.uid
}
1
  • See here. Which may help you. Otherwise, as a workaround, you can specify your own key resolver, like this Commented Nov 22, 2016 at 3:19

1 Answer 1

1

I'm sure by now you have figured out the solution for this, but for future people who come across this question.

Set the KeyId for the X509SecurityKey

x509Data.Select(cert => new X509SecurityKey(new X509Certificate2(Encoding.UTF8.GetBytes(cert.Value)))
            {
                KeyId = cert.Key
            })
            .ToArray()

This will allow the TokenValidationParameters to look up which issuerKey to validate against.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.