Nowadays, many users prefer using federated login, such as Google Sign-In, Facebook, Twitter and others, over having to create a new account for every service they use. Each user has their own favorite federated login provider, and it would take a lot of effort to integrate and manage each federated login provider for your app. This is where Firebase Authentication can help.
Firebase Authentication supports many popular federated login providers. You just need to integrate with Firebase Authentication, and let Firebase automatically manage multiple federated login providers under the hood for you.
However, depending on where your users are in the world, they may prefer a federated login providers for which Firebase does not have built-in support yet. For example, in Japan and many Asian countries, LINE Login is very popular with hundreds of millions of users, so you may want to support it as well. Fortunately, it is fairly simple to integrate LINE Login, as well as many other federated login, with Firebase Authentication using Custom Auth.
In one of our previous blog post, we have shown how to support federated login that was not available out-of-the-box with Firebase Authentication on the web using our JavaScript SDK. In this blog post, I will show you how to integrate with LINE Login on iOS and Android.
Here is how the login flow looks like:
Step 1: Use LINE Login SDK to log user in, and acquire their LINE Access Token
Step 2: Send their LINE Access Token to your server and validate it with LINE authentication server. If the token is valid, then create a Firebase Custom Auth token correspond to the user, and send it back to user's device.
Step 3: Use the Firebase Custom Auth token to login to Firebase from the device.
You will need to do some setup work to get your LINE business account and Firebase project ready.
Refer to LINE Login document (iOS / Android) to integrate LINE SDK to your app and implement LINE Login flow. Once user has successfully logged in, you can get their LINE access token as below:
iOS (Objective-C)
NSString *lineAccessToken = self.lineAdapter.getLineApiClient.accessToken;
Android
LineAuthManager authManager = LineSdkContextManager.getSdkContext().getAuthManager(); final String accessToken = authManager.getAccessToken().accessToken;
Then you can use your favorite networking library to send the access token to your own server for validation. In this sample code, I use GTM HTTP Fetcher for iOS and Volley for Android.
NSURL *url = [NSURL URLWithString:@"https:///verifyToken"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; NSDictionary *token = @{@"token" : lineAccessToken}; NSError *error; NSData *requestBody = [NSJSONSerialization dataWithJSONObject:token options:kNilOptions error:&error]; [request setHTTPBody:requestBody]; GTMHTTPFetcher *fetcher = [GTMHTTPFetcher fetcherWithRequest:request]; [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { if (!error) { // Extract Firebase Custom Auth token from response // ・・・ } }];
HashMap validationObject = new HashMap<>(); validationObject.put("token", accessToken); Response.Listener responseListener = new Response.Listener() { @Override public void onResponse(JSONObject response) { // Extract Firebase Custom Auth token from response // ・・・ } }; JsonObjectRequest fbTokenRequest = new JsonObjectRequest( Request.Method.POST, "https:///verifyToken", new JSONObject(validationObject), responseListener, errorListener); NetworkSingleton.getInstance(activity).addToRequestQueue(fbTokenRequest);
You will need a server to validate LINE access token and generate a corresponding Firebase Custom Auth token for that user. You can build a simple one with Firebase Node.js Server SDK and Express web server.
Firstly, your server receives the LINE Access Token from user's device and validates it using LINE Social Rest API. Don't forget to verify the channelId value in API response to make sure that the access token is actually issued for your app. This is to prevent spoof attack, of which attackers reuse access token from other app/channel to attempt login to your app.
Server (Node.js)
app.post('/verifyToken', (req, res) => { if (!req.body.token) { return res.status(400).send('Access Token not found'); } const reqToken = req.body.token; // Send request to LINE server for access token verification const options = { url: 'https://api.line.me/v1/oauth/verify', headers: { 'Authorization': `Bearer ${reqToken}` } }; request(options, (error, response, body) => { if (!error && response.statusCode === 200) { const lineObj = JSON.parse(body); // Don't forget to verify the token's channelId to prevent spoof attack if ((typeof lineObj.mid !== 'undefined') && (lineObj.channelId === myLINEChannelId)) { // Access Token Validation succeed with LINE server // Generate Firebase token and return to device const firebaseToken = generateFirebaseToken(lineObj.mid); // Update Firebase user profile with LINE profile updateUserProfile(reqToken, firebaseToken, lineObj.mid, () => { const ret = { firebase_token: firebaseToken }; return res.status(200).send(ret); }); } } const ret = { error_message: 'Authentication error: Cannot verify access token.' }; return res.status(403).send(ret); }); } });
After successfully validated LINE Access Token, use Firebase Server SDK to generate Firebase Custom Auth token and return it to the user device. You can reuse LINE's user ID for your Firebase user ID.
function generateFirebaseToken(lineMid) { var firebaseUid = 'line:' + lineMid; var additionalClaims = { provider: 'LINE' }; return firebase.auth().createCustomToken(firebaseUid); }
We also have a Firebase Server Java SDK.
You can make use of solutions like App Engine Flexible Environment or Cloud Functions to free yourself from managing the server.
After receiving the Firebase Custom Auth token, just use it to sign the user in Firebase:
[[FIRAuth auth] signInWithCustomToken:firebaseToken completion:^(FIRUser * _Nullable user, NSError * _Nullable error) { // Process sign in result // ・・・ }];
FirebaseAuth.getInstance() .signInWithCustomToken(firebaseToken) .addOnCompleteListener(new OnCompleteListener() { // Process sign in result // ・・・ });
Our sample code is open source. Feel free to download and give it a try. https://github.com/firebase/custom-auth-samples/tree/master/Line