Closed LarryBarker closed 5 years ago
Hey Larry!
I had a method signInWithCustomToken()
in a previous release of the SDK (not here in the tokens package, though), but removed it to emphasize that on a server, we are in the context of an administrative environment and some people were confused on why it didn't work as they expected or why they weren't able to sign in with a Facebook or Google Auth token.
That being said, you can't verify a custom token, only ID Tokens can be verified. The flow here would be:
kid
header and which can be verified via the verifyIdToken()
method.verifyIdToken()
method to a string (the method returns an instance of \Lcobucci\JWT\Token
(see https://github.com/lcobucci/jwt/tree/3.2)Long story short, you can see an example in action at https://github.com/kreait/firebase-php/blob/master/tests/Integration/AuthTest.php#L145-L159 (I'm dogfooding the SDK in my own Integration Tests 😅)
Interesting. So it sounds like we not even need to worry about getting the ID token back from the mobile client if the mobile client can use the custom token to authenticate on their end. Am I understanding that correctly?
I'm not concerned about the Firebase user doing anything to the real time db/Firestore from the Laravel app; the mobile client would be handling all the interaction there.
Thanks for the quick reply, let me know what else you may think.
I believe you're correct, I thought just now of looking up https://firebase.google.com/docs/auth/ios/custom-auth and https://firebase.google.com/docs/auth/android/custom-auth , and it seems indeed that creating and sending over the custom token should definitely be enough \o/
Sweet, that definitely simplifies my part. I modified my code a bit using your test and have this now:
$serviceAccount = ServiceAccount::fromJsonFile(__DIR__ . '/bg-rep-firebase-adminsdk-baomg-ed357f2f41.json');
$firebase = (new Factory)
->withServiceAccount($serviceAccount)
->create();
$auth = $firebase->getAuth();
$customToken = $firebase->getAuth()->createCustomToken('AE0xzvmtu7Ox85S9jYJ0zt7Y8yH2');
$idTokenResponse = $auth->getApiClient()->exchangeCustomTokenForIdAndRefreshToken(
$customToken
);
$idToken = json_decode($idTokenResponse->getBody()->getContents(), true)['idToken'];
try {
$verifiedIdToken = $auth->verifyIdToken($idToken);
} catch (InvalidToken $e) {
echo $e->getMessage();
}
$uid = $verifiedIdToken->getClaim('sub');
$user = $firebase->getAuth()->getUser($uid);
dd($user);
This will take an existing user and create a custom token in the Laravel backend, and then exchange it for a ID token which I'm assuming could be used to authenticate back in the Firebase app. However, knowing the UUID of the user eliminates the need for this because you already have the user. As soon as our mobile guy has a minute we're going to try using the custom token to authenticate in the mobile app. I'll keep you posted if you're interested.
Yes, please! But if you're using the Firebase Client SDK in your mobile apps, I'm not sure you need to exchange the custom token for an ID token anymore, the client SDK on the mobile device can do that (unless I miss a step in the process) - so as far as I see it at the moment, you need to create the custom token on the backend to be able to sign it with your service account's private key, but if you send that back to your mobile clients, the should be able to use the custom token directly to sign into Firebase.
The ID token is usually only needed if you want to use the access token to connect to the Firebase via their HTTP APIs.
(And the ID Token verification is usually meant to verify an ID token that has already been created by a client, to verify that the client token is legit).
So, no ID token verification on the backend needed, right? (And no code changes in the Tokens PHP Library, I would prefer not to have to touch it before the next refactoring 😅)
Authenticate a NodeJS server with (firebase-admin) to access laravel endpoint for example updating user data
const admin = require( "firebase-admin" );
const axios = require( 'axios' ).default;
//Separate module
const refreshedToken = require( './init-firebase' );
const _axios = axios.create( {
baseURL: 'https://example-laravel-server.com/api/server'
} );
async setupAxiosHeaders () {
const auth = admin.auth();
const custom = await auth.createCustomToken( 'some-firebase-uid' )
const token = await refreshedToken(custom);
_axios.defaults.headers.common[ 'Authorization' ] = `Bearer ${ token }`;
}
//App Init
(async () => {
await setupAxiosHeaders();
const { data } = await _axios.get('/me');
console.log('Authenticated me:', data);
//Your code
})();
init-firebase.js
const firebase = require( 'firebase/app' )
require( 'firebase/auth' )
const config = {
apiKey: "api-key",
authDomain: "project-id.firebaseapp.com",
databaseURL: "https://project-id.firebaseio.com",
projectId: "project-id",
storageBucket: "project-id.appspot.com",
messagingSenderId: "sender-id",
appId: "app-id",
measurementId: "G-measurement-id",
}
firebase.initializeApp( config )
module.exports = refreshToken = async ( token ) => {
try {
const firebaseToken = await firebase.auth().signInWithCustomToken( token )
return firebaseToken.user.getIdToken();
} catch ( error ) {
console.log( error );
}
}
Hello, thanks for putting this and your other package together. I notice there is no method to sign back into Firebase with a custom token. The docs show an example using the method
signInWithCustomToken
and I was wondering if there is a way to implement this?I have a Laravel backend where our authentication is taking place. I am trying to build a way for our mobile app to authenticate to the Laravel app and have the Laravel app generate a Firebase token the mobile app can use to access the real time db/Firestore. Is this something that can be accomplished?
I have been able to generate the token using this code:
$serviceAccount = ServiceAccount::fromJsonFile(DIR . '/firebase-adminsdk-baomg-ed357f2f41.json');
``
but when I try to authenticate using this code:
I am gettting:
message": "The header \"kid\" is missing.",
From what I have read, it seems the
verifyIdToken
method is used to verify a valid token already on Firebase and I am looking for a way to validate the custom token generated by my Laravel backend auth.Thanks again, I look forward to any advice or suggestions you may have.