How to handle request to callback URL with Firebase OAuth? - firebase

I am implementing Firebase OAuth with Twitter in a Game Maker app.
Note that Game Maker does not support SDKs so I am using 3-legged OAuth sign-in with REST.
After redirecting the user to the sign-in page for Twitter, I don't know how to handle the callback to the firebase URL and get the authentication data back to my Game Maker client.
I got the first step of the sign-in working, which is the POST oauth/request_token request to api.twitter.com; in the response I'm receiving oauth_token, oauth_token_secret and oauth_callback_confirmed.
After that, I'm opening the following URL in the user's browser: "https://api.twitter.com/oauth/authenticate?oauth_token=[oauth_token]"
That sends me to the Twitter sign-in page, which then redirects to the callback URL set in Firebase (and whitelisted in the Twitter dev console): "https://[APPNAME].firebaseapp.com/__/auth/handler" with the oauth_token and oauth_verifier query parameters.
The guide says this about this step of the 3-legged sign-in:
Upon a successful authentication, your callback_url would receive a request containing the oauth_token and oauth_verifier parameters. Your application should verify that the token matches the request token received in step 1.
I don't know how to reiceve the request to the callback_url and process it. Is it something I'm supposed to do from Firebase itself? Is my Game Maker client supposed to do it with a GET request? I have no clue.

I ended up setting up a Cloud Function as a callback.
This way I am retrieving the response directly from the function and storing the data/errors in the database.

Related

How to pass Firebase Custom Token to client?

I have a project that requires the usage of login via Facebook and Google, so I picked Firebase to speed up the process of authentication; However, the user must also be able to login via LINE(a messaging app popular in SEA).
Currently, I have implemented:
Line Login-> Finish Login -> Redirect to Cloud Functions -> Verify Line's Access_Token -> Create a User In Firebase from LINE's ID Token -> Create Custom Token from Firebase User
All that's left is to implement signInWithCustomToken and then get the idToken from firebase to send to my api for authorisation.
Now, the signIn process should be handled by the client side, but I am not sure how to pass the customToken to the client side(Our backend api and frontend client is separated).
I could pass it in a query param as I redirect the user to the frontend, but I am not sure if that's the best way to go about it.
What should I do?
After the user has logged in to LINE, it redirects to any link you set
for it to redirect to with the url params being the authorisation code
and state, so ?code=xxxxxx&state=xxxxx ... I decided to use cloud function to be the redirect url for the LINE Login
If I understand correctly, instead of directly redirecting LINE to the Cloud Function, you should probably redirect to a page of your web application which, in turns, calls a Callable Cloud Function (passing the code and statevalues as arguments).
This Cloud Function verifies the token as well as creates a user in Firebase and when this is done, sends back the token to the page of your web application. You then have all the elements to call the signInWithCustomToken() method.

Trouble using Firebase Auth to access google API via gapi SDK

In my firebase (Angular) app, I'm using firebase authentication to log a user in via their Google Profile. As part of this process, the user gives me permission to access their gmail account (scope 'https://www.googleapis.com/auth/gmail.compose').
After the user has logged in this way, I want to configure the "gapi" google javascript SDK so that the "signed in user" is the user signed in via firebase auth. Here's where I'm having trouble.
It appears that I need to set the client token for the gapi sdk like so gapi.client.setToken(userAccessToken) and the token needs to be set before the gapi client is initialized. Attempting to do this doesn't seem to work however (a call to gapi.auth2.getAuthInstance().isSignedIn.get() returns false when it should return true).
I also can't figure out a way of changing the "signed in user" if the firebase user logs out and a new one logs in. This is because, again, the gapi client seems to require the gapi.client.setToken() be called before the client is initialized, and I can't see any way of re-initializing and already initialized gapi client.
I can get the gapi client working if I use the gapi client's own gapi.auth2.getAuthInstance().signIn() method, but then the user is asked to sign in to my app twice using (from the user's perspective) identical google login popup boxes (one prompt originating from firebase auth and the other from the gapi client).
Does anyone have any suggestions / tips? After someone logs in via firebase auth I can get access to their userAccessToken, I just can't figure out how to programmatically pass that to the gapi client in a clean way.
Ideally:
on application load the gapi client would also load and initialize.
When a user chose to sign in, I would be able to use Firebase Auth to log someone in via their google profile, then get their access token and pass it to the gapi client to make google api calls.
If the firebase user ever logged out, I would clear the gapi client's api token.
If a new firebase user logged in, I would re-set the gapi client's api token.
I have come upon a placeholder (i.e. non-ideal) solution to this problem by following this S.O. answer.
In short, the GAPI client does not seem to let you manually pass it an access token, but the firebase auth client does let you manually pass it an access token. So, instead of handling authentication with the firebase sdk and passing the token to the GAPI client, you need to do the reverse and handle authentication with the GAPI client and then pass the token to the firebase SDK.

How do I return an auth token to the google assistant using a website?

I want to implement an Actions for Google app that links to user account in a Firebase project and query's their data. I have a website that is set up using Firebase UI that logs them in and redirects them to a dummy page that basically just says "You have been logged in." I cannot see any documentation anywhere that shows how to return this auth token to google so the assistant can use it to query things on their account. Does anybody know how to accomplish this? I am using this documentation https://developers.google.com/actions/identity/google-sign-in-oauth?creation=no. This is the specific text I am not understanding.
"Your service creates an access token and returns it to Google by redirecting the user's browser back to Google with the access token attached to the request."
This basically means that, instead of returning a new page, you issue an HTTP redirect to a URL that they have sent you as part of the request. You will need to add some parameters to this URL that include the auth info, and this is how Google will get the information - via the redirect handled by the user's browser.
They provide some details further down in step 4 on that page, which reads
Send an HTTP response that redirects the user's browser to the URL
specified by the redirect_uri parameter. Include all of the following
parameters in the URL fragment:
access_token: the access token you just generated
token_type: the string bearer
state: the unmodified state value from the original request
The following is an example of the resulting URL:
https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID#access_token=ACCESS_TOKEN&token_type=bearer&state=STATE_STRING

sign in with slack and validate request from firebase backend for the angular app

i have built a webapp using angular material and firebase functions + realtime DB as the backend. I am using slack "Sign in with Slack" API oauth flow. All works well and i am able to generate a accessToken in the backend which i can store against the user in the realtime DB. Once that is done i make a redirect call to my angular app on the dashboard page. Currently i am passing userid in the redirect url which i use to drive user to dashboard and show his data.
This functionally works fine but is a big security issue. As i can directly type the redirect url and boom. I am in the dashboard.
So, how do i solve this? What should i be doing in the url redirect that is secure and validates the response is the the result of a valid request?
I am not familiar with the Slack OAuth SDK but in general, this is true for all OAuth providers. Ideally, at the point where you redirect to your callback URL with the slack authorization code and you exchange the auth code for a Slack access token before returning that access token to the client, you call the Slack API to get the Slack user ID with the access token and then mint a Firebase custom token with that uid. You then return that custom token to the client and signInWithCustomToken. Make sure you are checking the state field (which you set when started the Slack sign in) along with Auth code to verify that the flow started and ended on the same device.

Retrieve Access Token with LinkedIn JS SDK to use in Back-end

Currently I have both Facebook and LinkedIn Oauth2 flow working fine. Because in some cases I don't want the user to redirect to another page, I use the Facebook JS SDK that works fine, retrieving the access token and sending it to the server where I retrieve user data with REST calls.
Unfortunately, I'm not having success in doing the same with the LinkedIn JS SDK. The official documentation isn't helpful at all in that regard: https://developer.linkedin.com/docs/getting-started-js-sdk.
I retrieve user data in the server because it's easy to forge fake data in the client side and send it to the server, so a client side solution for that is not an option.
If I try to use the token that I get in js in the REST API I get Invalid access token. (401)
There are several opened questions that doesn't have any response (or a helpful response) here in SO:
2015-08-03 - No response:
Javascript: Linkedin Access TOken
2016-05-29 - No response:
can I get access token through LinknedIn JS SDK?
2016-08-31 - No helpful response (data is retrieved in the front-end):
How to Get Access Token Using LinkedIn API JavaScript SDK
2017-06-30 - No helpful response:
LinkedIn OAuth token with Javascript SDK
In the below question, there is a comment that says what I'm already guessing:
[...] Honestly I think the JS API is completely useless like this
because if you can't verify/use the token server-side you basically
cannot trust any of the information.
2015-07-22 - No helpful response (data is retrieved in the front-end):
get linkedin Access Token with JavaScript SDK
There's some information about exchanging the Javascript API tokens with a REST API OAuth token, but in the references I've found the links are broken (and it would be impractical to do this, depending on the complexity, instead of using the token directly, like in the Facebook JS SDK):
http://developer.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens
https://developer-programs.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens
So, I would like to know if there is some way to login with LinkedIn using the JS SDK and retrieve the user data in the back-end using REST calls (like I do in the Oauth2 flow), hopefully with official docs.
I've had the same problem and the only way I found to use the JS token was to add the header oauth_token instead of an Authorization Bearer header:
POST https://api.linkedin.com/v1/people/~:(id,firstName,lastName,picture-url,email-address)?format=json
Headers {
'oauth_token': JS_TOKEN
}
The JS_TOKEN I'm reading on frontend from IN.ENV.auth.oauth_token.
I've been struggling with the same issue for some time, this is the way I solved it (not using the JS SDK):
Step 1: you send your user to the LinkedIn login page, in the redirect_uri param use an endpoint to handle all the logic related to LinkedIn.
Step 2: When the user finishes login in, Linkedin is going to send a GET request to that endpoint, this request will have an "Authorization Token", this token is just a temporal token and it won't allow you to get your user's data.
Step 3: Use the Authorization Token you just received and send a post request to Linkedin
Step 4: Linkedin will send you back an Access Token (this is the one you are looking for), now you can request all the information you want
Step 5: Redirect your user back to your web app.
The structure of the request as well of the anchor tag params are available here: https://developer.linkedin.com/docs/oauth2

Resources