Reputation: 1354
I've an existing project that is built on :
I'm in process of rewriting the frontend to move to Angular 8 and I want to leverage the firebase features.
I'm currently working on integrating the authentication feature (username/password, google, twitter, facebook etc...)
And I'm thinking about my next step :
I was imagining something like :
Would this work ? any suggestions ?
Upvotes: 2
Views: 225
Reputation: 1354
So here is how I did it :
On the client side (Angular Application), I use ngx-auth-firebaseui, to display the login form.
On the form, I set the call back that handle an authentication success:
login.component.html
<ngx-auth-firebaseui (onSuccess)="successfulLogin($event)"
(onError)="printError($event)">
</ngx-auth-firebaseui>
The code of the callback is here. From the Firebase User object, I call the method getIdTokenResult() to get the firebase JWT. And I then call my php backend via the authenticationService
login.component.ts
successfulLogin(user:User) {
console.log(user);
user.getIdTokenResult().then((idTokenResult:IdTokenResult)=> {
console.log(idTokenResult.token);
let token : string = idTokenResult.token;
let rcqJWTToken = this.authenticationService.authenticate( { token } as FirebaseJWT);
rcqJWTToken.subscribe((rcqToken:string)=> console.log("RCQ JWT Token : '"+rcqToken+"'"));
this.router.navigate['/welcome'];
});
}
Here I transmit the Firebase JWT to my php backend authentication.service.ts
authenticate(firebaseJWTToken:FirebaseJWT):Observable<String>{
return this.http.post<String>(this.authenticationURL, firebaseJWTToken, httpOptions)
.pipe(
tap(_ => console.log('fetched RCQ JWT')),
catchError(this.handleError<String>('authenticate', ""))
);
}
On the server side :
I set the GOOGLE_APPLICATION_CREDENTIALS as an env var, like it is when deployed on Google App Engine
putenv("GOOGLE_APPLICATION_CREDENTIALS=/Users/myuser/.cred/GCP-project-ID.json");
I use Slimframework, so I instanciate the Firebase object in my dependencies.php file. With the env var, Firebase do not need anything else. check here : https://firebase-php.readthedocs.io/en/4.32.0/setup.html
use Kreait\Firebase;
use Kreait\Firebase\Factory;
/**
* Used to authenticate a firebase user, from it's Firebase JWT
* @property Firebase $firebase
* @param \Slim\Container $c
* @return Firebase
*/
$container['firebase'] = function (\Slim\Container $c)
{
$firebase = (new Factory)->create();
return $firebase;
};
and here comes the route where the authentication is done :
$app->post(getPrefix().'/firebase-authenticate', function($request, $response, $args) use ($app)
{
$token = $this->clientInputValidator->validateString("token" , $request->getParsedBodyParam("token" ), 1500 , true );
$username = "";
Logger::dataForLogging(new LoggingEntity(null, ["username"=>$username]));
try
{
$verifiedIdToken = $this->firebase->getAuth()->verifyIdToken($token);
}
catch (InvalidToken $e)
{
$response401 = $response->withStatus(401);
$response401->getBody()->write(json_encode(["error" =>"Authentication error"]));
$this->logger->error("Firebase authentication error", array('username' => $username, 'token' => $token));
return $response401;
}
$uid = $verifiedIdToken->getClaim('sub');
$user = $this->firebase->getAuth()->getUser($uid);
$this->logger->debug("Firebase JWT checked successfully", array('uid' => $uid,'user' => $user));
});
The main thing is here :
$verifiedIdToken = $this->firebase->getAuth()->verifyIdToken($token);
And the user details are retrieved here:
$user = $this->firebase->getAuth()->getUser($uid);
I can get the uid, email, and all the info in the Firebase JWT.
the token itself has a TTL of 1 hour, so I'll probably have to refresh the token and revalidate it against my backend.
Upvotes: 0