transistor
transistor

Reputation: 921

Firebase 3 Auth + Node + jsonwebtoken: Invalid custom token

I have my own OAuth 2 server running on Node.js v4.4.5, with all this stuff:

"bcrypt-nodejs": "0.0.3",
"body-parser": "^1.15.1",
"cors": "^2.7.1",
"express": "~4.1.1",
"firebase": "^3.0.3",
"mongoose": "^4.4.19",
"oauth2orize": "^1.3.0",
"passport": "^0.3.2",
"passport-jwt": "^2.0.0",
"passport-local": "^1.0.0"
"jsonwebtoken": "^7.0.0"

I can login and get a JWT that, according to jwt.io, can be decoded, but I can't verify since I don't have the public key.

I get the JWT and send it to signInWithCustomToken and then I get an error from https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=AIzaSy....

{
        "error": {
        "errors": [
        {
            "domain": "global",
            "reason": "invalid",
            "message": "INVALID_CUSTOM_TOKEN"
        }
        ],
        "code": 400,
        "message": "INVALID_CUSTOM_TOKEN"
    }
}

In my auth.js controller, I have create the JWT like so:

var token = jwt.sign(
    {
        iss: jwt_config.client_email,
        sub: jwt_config.client_email,
        aud: 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
        iat: iat,
        exp: exp,
        uid: user._id,
        claims: {
            username: user.username, 
            user_id: user._id, 
            roles: user.role
        }
    },
    jwt_config.private_key, 
    {
        algorithm: 'RS256'
    }
);
res.json({success: true, token: token});

I load the service account data into jwt_config:

var jwt_config = require('../config/Firebase-68824d8xxxxx.json');

This is the offending JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwcm9qZWN0QHByb2plY3QtODE5NTMxNDA4ODMzNzM0MzUwMy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInN1YiI6InByb2plY3RAcHJvamVjdC04MTk1MzE0MDg4MzM3MzQzNTAzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9pZGVudGl0eXRvb2xraXQuZ29vZ2xlYXBpcy5jb20vZ29vZ2xlLmlkZW50aXR5LmlkZW50aXR5dG9vbGtpdC52MS5JZGVudGl0eVRvb2xraXQiLCJpYXQiOjE0NjQ1ODIzMDEsImV4cCI6MTQ2NDY5MDMwMSwidWlkIjoiNTc0YTJmNWJmODRhZTMwOTdkMjNiZWQ1IiwiY2xhaW1zIjp7InVzZXJuYW1lIjoiamxwZWxsaWNlciIsInVzZXJfaWQiOiI1NzRhMmY1YmY4NGFlMzA5N2QyM2JlZDUiLCJyb2xlcyI6IlN0dWRlbnQifX0.gDghMzXc2sFP4XbMhrU2kxo7u0yte4PT03AbeyzT8oGLYJEHJOAY-kZT0l_fGWDi68AfVCaEiHeFj1a3-M95i4NRTQErWyGPuqqS9ii2m0mDaBseFZumk5iTTWiqY8Tpo6_7fkWGsuM7fnuXjaMKV8jkOWS913EE3DQmXHT5bwPe-ky-xTFxU0P3VPWzbgw5T5lExmzpv0x78Fr-RCy45QhfJ3IeVa-Pyhnp4_NY9VAi1naJLpwKKo7aVq3uLujMK8ViNSgfdXTqI9VNq7KrdgqSKnpdoZ2ph_J6fHBnHtAhV6F_Iy_FyC7Zg1EyC_4vMpBJuMx5UYzy6f1Gm0wvHw

When I recieve it back at mi login page, I send it to Firebase:

firebase.initializeApp(config);
$.ajax({
    type: 'post',
    dataType: 'json',
    url: 'http://ec2-52...compute.amazonaws.com:3000/api/authenticate',
    data: $('#loginForm').serialize(),
    complete: function(result) {
        result = result.responseJSON;
        // console.log(JSON.stringify(result, null, 4));
        var success = result.success;
        if (success) {
            var data = result.token;

            firebase.auth().signInWithCustomToken(data).catch(function(error) {
                // Handle Errors here.
                var errorCode = error.code;
                var data = error.message;
                // ...
            });

        } else {
            var data = result.message;
        }
        $('#token').html(data);
    }
});

And here is where the error pops up.

I'm stumped, what should I do?

should I look into a different module to create the JWT?

Is there some way to know what is specifically wrong about the JWT?

Thanks!

Upvotes: 3

Views: 2045

Answers (2)

gae123
gae123

Reputation: 9457

In a similar situation, the token created on the server side had been created with an expiration of 2 hours. There was no error when creating the token, only when trying to use it on the client side. Changing the expiration to one hour fixed the "Invalid Custom Token" problem.

Upvotes: 0

transistor
transistor

Reputation: 921

Well, I did it! Turns out that in my claims, username and user_id were objects! So, by doing this:

claims: {
    username: String(user.username), 
    user_id: Strint(user._id), 
    roles: user.role
}

it works!

Hope someone finds this helpful.

Upvotes: 2

Related Questions