How to implement Facebook login via its official JS SDK
Most often in universal javascript project we tends to use passport.js
. But a recent project requires to use the official SDK. The article will walk you through the flow with example code. Hope it could get you started. Even you just use passport.js
or other languages, after reading this article, you should understand what happens underneath.
We use plain Express
as our backend.
1. Brief
The basic idea of authentication is just to get the identity to verify who you are so you could later on use to access some authorized resources. Here we just let the facebook do it for us, so we can confirm that is user is trustable. The thing we used to identify the user is called access token
. You can use the token to a
2. Workflow
Before we even start, let’s review what will happen next?
2.1 Flow
Place the Facebook button along with its
javascript
code, it will render a blue login button on the page. Press the button, it will leads the user to the facebook login page.After the user grants the permission to our app, it will go to the callback URL you assigned at facebook developer portal along with an short-life access token.
Two things could happen after the last step:
- You should exchange for a long life token with the previous one.
- You could get some user information via the short life token.
Save the user to the database.
Generate a
JSON web token
(jwt) with your own signature and passback it back to the client.The client could use the token to access an authorized endpoint.
2.2 Tip
If you just use facebook to authenticate a user, you could skip step 4 entirely. Because when your
jwt
expires, you could simply let the user login via facebook again.The sub-steps in Step 3 could happen at the same time. Which means you could use
Promise.all
to make it happen faster.A trick in step.2 is facebook won’t redirect you to the callback URL as it did when you use
passport.js
, but don’t worry here. You can still get the access token in the client side js.
3. Code for each step.
3.1 Add facebook button
1 | <div |
Add Zepto
and your own javascript file.
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script> |
Now add the code for that login button, 2 things to notice,
- In the
FB.init()
, add your own app ID. - The
if
else
insideFB.getLoginStatus
is where add your own logic.
1 | // browser-auth.js |
3.2 Get the short life access token
It seems no matter what you set in that Valid OAuth redirect URIs
in Developer portal, if you use official SDK, it won’t go there. So, how do you get the access token? It will trigger the checkLoginState()
that you just set and pass the token as the parameter.
Now let’s assume the user grants our permission. We need to implement the startToAuth()
1 | function startToAuth(response) { |
This is what the token looks like:
1 | { |
3.3 Add the middleware you need to Promise.all
the 2 sub-steps you need for Step 3
We need to exchange for the long time token and we need to retrieve the user information via the short time token.
1 | const asyncAllFBAuth = (req, res, next) => { |
I assume you might have interests for the blog I wrote previously: 3 interesting experiments of Promise.all()
This is how you exchange for the long time token:
1 | const exchangeLongTimeToken = req => { |
This is how you retrieve the user information:
1 | const retrieveUserInfo = req => { |
TIPS:
Notice the fields
there, it contains all the fields which you wanna retrieve from facebook. And the fields you see here, is the most possible fields you could get via the default permission. Feel free to copy it.
3.4 Issue a JWT with the information you want
Such that next time, when the user provide a valid jwt for login, you will get all the information in the below signUser
variable without accessing the database.
1 | const issueJWT = (req, res, next) => { |
3.5 Finally, send the JWT back to the client.
1 | const fbLogin = (req, res) => { |
The whole route looks like this:
1 | router.post( |
I commented some validation and saving middleware here just for convenient, you need to do it if you wanna use it in production.
3.6 Now, modify the code in 3.2
1 | function startToAuth(response) { |
We just route to the URL which should display after successfully login here. It should be a protected resource. The reason we can access that is we already save that token to the cookie in the saveToCookie
middleware.
WARNING: Make sure you handle the CSRF problem when you implement the
saveToCookie
middleware.
4. End
It is basically all of it. Hope it helps. Or feel free to solve that problem of why it won’t redirect me to the callback URL since maybe there’s something I was missing. :)
Thanks for reading!
Follow me (albertgao) on twitter, if you want to hear more about my interesting ideas.