Authentication with React Native and API backend - node.js

I'm trying to wrap my head around oauth with a React Native app and a separate NodeJS/Express API backend. I understand https://github.com/adamjmcgrath/react-native-simple-auth offers authentication for a React Native app and http://passportjs.org/ offers authentication for a NodeJS backend. I'm unsure how to connect these two for authentication for login and access to the API.
I'd like users to login to the React Native app either by email and password or via Facebook/Twitter/Google. Once logged into the app, what do I send to the API to make sure they are authenticated and have access to a specific route?
Here is an example flow to login and see the logged-in user's settings:
User logs into React Native app via email/password or Facebook/Twitter/Google.
User is authenticated
App makes request to GET /api/settings
API verifies user is authenticated and returns that user's settings or API verifies user is not authenticated and returns a 403.

There's a whole lot to this question, so much so that it wouldn't all fit in a single SO answer, but here's some tips and a general outline that should broadly fit into what you want to accomplish.
OAuth2 Authorization
From the sounds of it, you are interested in using OAuth 2 to provide social login authorization, and would like to do first-party authentication as an alternative with an email and password. For social logins you will end up using the OAuth 2 Implicit flow to retrieve an access token, which is a widely recognized pattern. Because you are also looking to authenticate users with an email and password, you may want to familiarize yourself with OpenID Connect, which is an extension of OAuth 2 and which explicitly supports authentication in addition to authorization.
In either case, once your user has either submitted an email/password combo or granted permission through the social identity providers, you will receive in response an access token and (optionally) an ID token. The tokens, likely a JWT (JSON Web Token, see jwt.io) will come across as a base64 encoded string that you can decode to inspect the results of the JWT, which will include things like the ID of the user and other details like email address, name, etc.
For more info on the different types of flows, see this excellent overview on Digital Ocean.
Using Tokens for API Authentication
Now that you have an access token, you can pass it along with all requests to your API to demonstrate that you have properly authenticated. You'll do this by passing along the access token in your HTTP headers, specifically the Authorization header, prefacing your base64-encoded access token (what you originally received in response to your authorization request) with Bearer . So the header looks something like this:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJh...
On your API's side, you will receive that token, decode it, and then verify the ID and claims in it. Passed as part of the token in the sub property will be the subject, or ID of the user making the request. This is how you identify access and start to do things on your API side with the respective user's rights, perms, etc. It is also important that you validate the access token once you receive it on your API side, to ensure it wasn't spoofed or hand-crafted.
How it looks in RN for Implicit flows
Here's what the general process looks like in React Native for OAuth 2 Implicit flows, which is what you'll use for social identity providers:
User taps one of your social login buttons on React Native UI
Your code that responds to the buttons will build a request URL to those providers, depending on what each wants (because it differs slightly).
Using the Linking API in RN, you will open up that URL in a browser on the device which sends the user off to the social provider for them to do the login/authorization dance.
Once complete, the social provider will redirect the user to a URL you provider. On a mobile device, you will use your own custom URL scheme to move the user from the web view to your app. This scheme is something you register as part of your app, such as my-awesome-app://, and the redirect URL you pass to the social provider could look like my-awesome-app://auth_complete/. See the Linking API docs for how to configure these URL schemes and deep linking.
In the handler for that new URL scheme/deep link, you'll get the tokens passed as part of the URL. Either by hand or using a library, parse out the tokens from the URL and store them in your app. It's at this point that you can start inspecting them as JWTs, and pass them along in the HTTP headers for API access.
How it looks in RN for Resource Owner Password Grant flows
You have the option for your email/password combo for your own accounts of either sticking with the Implicit flow, or switching to the Resource Owner Password Grant flow if your API and app are trusted by each other, meaning that you are making both the app and the API. I prefer the ROPG flow on mobile apps where possible because the UX is much nicer--you don't have to open up a separate web view, you just have them type in their email and password into UI elements directly in the app. So that being said, here's what it looks like:
User taps the email/password combo login button, and RN responds with a UI that includes TextInputs for the email and password
Build a POST request to your authorization server (which may be your API, or may be a separate server) that includes the properly crafted URL and body details that passes along the email and password. Fire this request.
The auth server will respond with the associated tokens in the response body. At this point you can do the same thing previously done in step 5 above, where you store the tokens for later use in API requests and inspect them for relevant user information.
As you can see, the ROPG is more straightforward, but should only be used in highly trusted scenarios.
At the API
On the API side, you inspect for the token in the Authorization header, and as mentioned previously, and if found you assume that the user has been authenticated. It is still good security practice to valid and verify the token and user permissions. If there is no token sent with the request, or if the token sent has expired, then you reject the request.
There's certainly a ton to it, but that provides a general outline.

Related

Make user registration requests from my frontend in Keycloak using its API directly

In my Angular application (Frontend) the users can sign-in as following:
The user will fill-up a login-form (username or email / password).
The user will click on Login and that will hit this endpoint: http://localhost:8080/auth/realms/REALM_NAME/protocol/openid-connect/token
The user will have an answer in JWT format and will get his access_token (jwt token), refresh_token... etc.
Now this token will be used to access my backend APIs that will check the validity of the signature of this token against the JWKs_URI (with the encryption RSA256).
The question now is : how can I enable user registration in the same way, which means, I wish that the user can:
Fill up a registration form
Enter his email, password, password confirmation, more info (attributes maybe)
The user will then click on Register and it will hit an endpoint in Keycloak (/register maybe) which will return some answer about the success of this registration.
BTW: I don't want to use the user management API.
You can use Keycloak Admin REST API to register new users. Make sure to not expose it carelessly.
Regarding you question, related to the authentication, you can register a Keycloak OIDC client. OIDC offers a bunch of resources you can use.
If you register your application as a Keycloak client that uses OIDC direct grant. Basically "direct grant" implies you can get an access token with just a simple POST to /realms/{realm-name}/protocol/openid-connect/token.
The documentation about direct grants is scattered across the Keycloak documentation and some details can only be found in the OIDC RFCs; so I found you this page that ties everything together.
Careful again ! It might be obvious but don't turn you Angular app into a OIDC client otherwise hacker will steal your Keycloak client's credentials. Make sure to have your Angular app call some server, where you'll implement the necessary safety mechanism to block abusive use of your client (for instance using CAPTCHA).

Should my app issue it's own access tokens, when using external oauth2 provider (facebook)?

I would like to give the users a possibility to login with some external oauth2 provider (facebook) in my app. The client's part is running on mobile device in a native app.
I am not sure which of the approaches below should I prefer ?
Should the client send the user's access token by facebook with each request ? At each request backend asks facebook to validate the access token. Based on the validation's result, backend performs authorization and return corresponding result to the client.
Should the backend ask facebook to validate the access token only at user logon, then issue its own access token, return the access token back to the client and client will use this access token at making requests to the server to avoid contacting facebook at each request ?
I have read some questions about how to implement the auth with facebook and most of the devs are using B, but I haven't seen any explanation why is it good/bad to use A ?
What I see as benefits of the solutions:
backend doesn't need to care about issuing, refreshing, validating access tokens since this is done only by facebook's authorization servers.
this solution seems to be more effective, since it does not require to connect to facebook at each request.
Security tokens issued by Facebook are signed with a digital signature. The API server only needs access to the public key to validate the signature. There's no need at all to contact Facebook after the user authenticates.
A reason to issue your own tokens after the user signed in with Facebook could be to add claims to the token. But obviously having your own authorization server comes at a cost. It's up to you to weigh the pros and cons.
If you do decide to have your own authorization server, make sure not to write your own! There are open source options like Thinktecture IdentityServer.
I will vote for option B and here is my explanation,
Your API must authorise the request every time with some auth token , which cannot be external provider token, in such case anyone with an access token (eg: other developers) of other provider can access your api, basically there is no auth here.
When your sever issue access token, it's easy to validate and when needed could be revoked easily (eg: on password reset)
While authenticating , your server has fully control over issuing access token , so the validation is made only once and doesn't have to do every time while calling the API.

How to connect a Javascript front end using Facebook Login and a PHP back end through OAuth 2.0?

I have the following elements:
A PHP back-end providing a RESTful API secured with OAuth (FOSOAuthServerBundle with Symfony 2)
A Javascript front-end (AngularJS), i.e. an OAuth client.
My goal is to provide users with an authentification page in the front-end, allowing them to log in and access the API through the Javascript.
I do this the following way, according to this article: http://www.bubblecode.net/fr/2013/03/10/comprendre-oauth2/ (unfortunately in French, but if you scroll a bit, the diagrams explaining the standard grant flows are in English):
I provide a form asking the user credentials (login and password)
I use an OAuth Implicit Grant to exchange the user credentials for an access token.
Evertything should work (almost) well so far.
Now, the reason of this question is I want to add Facebook Login to my front-end. What this will give me is a Facebook access token each time a user registers with Facebook Login on my front-end. Ideally, my back-end should:
get this token
check it against Facebook PHP API in order to validate it
retrieve from Facebook PHP API the user Facebook UID
compare it to the ones of my app registered users
return an access token (this time for my own app, not Facebook) if and only if the Facebook UID matches with one of my registered app users.
My question is: which type of grant should I use to make the transaction between my front-end and my back-end in such a use case (given that it is of course not acceptable to give my Client Secret from a Javascript Client)?
Actually, I managed to found the solution. A custom grant should be designed to solve this problem, based on the Implicit Grant (in which the Client Secret is not asked).
However FOSOauthServerBundle does not yet implement grants based on public clients (see https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/issues/266 for more details).

Using OAuth instead of Basic authentication?

We have a web service, which currently uses Basic Auth over https to authenticate user requests. We also have a website which uses the service, and a native Windows client, which also uses the web service. I've read about OAuth, and it seems like it's always used for giving or getting access to external resources, i.e. delegation, but I'm trying to understand if it's a replacement for Basic Auth.
I'm not quite sure how all the parts fit together. Do you use Basic over https to the website to retrieve a secret and then have the javascript which is making requests to the REST services authenticate to the web service using OAuth instead of Basic?
It seems that at some point the user needs to enter their username and password into a form. I'm not sure what typically happens next. Is this even a use case for OAuth?
If you have local database accounts for the users (Resource owners) then you can replace the basic authentication with the one of OAuth flow named "Resource Owner Password Credentials" flow.
It is very simple flow where you issue HTTP post to an end point specified in your HTTP server usually named /token The content-type for this HTTP Post action is x-www-form-urlencoded, so the post body will contain something like this grant_type=password&username=Taiseer&password=SuperPass
One the request is sent to the /token end point the server will validate the user credentials against your database store, and if all is valid it should generate a token (signed string) which contains all the claims for this resource owner (user). Then your client application should present this token in the Authorization header with each call to any protected end point using bearer scheme.
This token expires after certain period and you can configure this from the AuthZ server. You can read my detailed blog post Token Based Authentication to get more details.

passport.js RESTful auth

How does one handle authentication (local and Facebook, for example) using passport.js, through a RESTful API instead of through a web interface?
Specific concerns are handling the passing of data from callbacks to a RESTful response (JSON) vs using a typical res.send({ data: req.data }), setting up an initial /login endpoint which redirects to Facebook (/login cannot be accessed via AJAX, because it is not a JSON response - it is a redirect to Facebook with a callback).
I've found https://github.com/halrobertson/test-restify-passport-facebook, but I'm having trouble understanding it.
Furthermore, how does passport.js store the auth credentials? The server (or is it service?) is backed by MongoDB, and I'd expect credentials (login & salted hash of pw) to be stored there, but I don't know if passport.js has this type of capability.
There are many questions asked here, and it seems that even though the questions are asked in the context of Node and passport.js the real questions are more about workflow than how to do this with a particular technology.
Let's use #Keith example setup, modified a bit for added security:
Web server at https://example.com serves a single page Javascript client app
RESTful web service at https://example.com/api provides server support to rich client app
Server implemented in Node and passport.js.
Server has a database (any kind) with a "users" table.
Username/password and Facebook Connect are offered as authentication options
Rich client makes REST requests into https://example.com/api
There may be other clients (phone apps, for example) that use the web service at https://example.com/api but do not know about the web server at https://example.com.
Note that I'm using secure HTTP. This is in my opinion a must for any service that is available in the open, since sensitive information like passwords and authorization tokens are passing between client and server.
Username/password authentication
Let's look at how plain old authentication works first.
The user connects to https://example.com
The server serves a rich Javascript application which renders the initial page. Somehwere in the page there is a login form.
Many of the sections of this single page app haven't been populated with data due to the user not being logged in. All these sections have an event listener on a "login" event. All this is client side stuff, the server does not know of these events.
User enters his/her login and password and hits the submit button, which triggers a Javascript handler to record the username and password in client side variables. Then this handler triggers the "login" event. Again, this is all client side action, credentials were not sent to the server yet.
The listeners of the "login" event are invoked. Each of these now needs to send one or more requests to the RESTful API at https://example.com/api to obtain the user specific data to render on the page. Every single request they send to the web service will include the username and password, possibly in the form of HTTP Basic authentication, since the service being RESTful isn't allowed to maintain client state from one request to the next. Since the web service is on secure HTTP the password is safely encrypted during transit.
The web service at https://example.com/api receives a bunch of individual requests, each with authentication information. The username and password in each request is checked against the user database and if found correct the requested function executes and data is returned to the client in JSON format. If username and password do not match an error is sent to the client in the form of a 401 HTTP error code.
Instead of forcing clients to send username and password with every request you can have a "get_access_token" function in your RESTful service that takes the username and password and responds with a token, which is some sort of cryptographic hash that is unique and has some expiration date associated with it. These tokens are stored in the database with each user. Then the client sends the access token in subsequent requests. The access token will then be validated against the database instead of the username and password.
Non browser client applications like phone apps do the same as above, they ask user to enter his/her credentials, then send them (or an access token generated from them) with every request to the web service.
The important take away point from this example is that RESTful web services require authentication with every request.
An additional layer of security in this scenario would add client application authorization in addition to the user authentication. For example, if you have the web client, iOS and Android apps all using the web service you may want the server to know which of the three the client of a given request is, regardless of who the authenticated user is. This can enable your web service to restrict certain functions to specific clients. For this you could use API keys and secrets, see this answer for some ideas on that.
Facebook authentication
The workflow above does not work for Facebook connect because the login via Facebook has a third party, Facebook itself. The login procedure requires the user to be redirected to Facebook's website where credentials are entered outside of our control.
So let's see how things change:.
The user connects to https://example.com
The server serves a rich Javascript application which renders the initial page. Somehwere in the page there is a login form that includes a "Login with Facebook" button.
The user clicks the "Login with Facebook" button, which is just a link that redirects to (for example) https://example.com/auth/facebook.
The https://example.com/auth/facebook route is handled by passport.js (see the documentation)
All the user sees is that the page changes and now they are in a Facebook hosted page where they need to login and authorize our web application. This is completely outside of our control.
The user logs in to Facebook and gives permission to our application, so Facebook now redirects back to the callback URL that we configured in the passport.js setup, which following the example in the documentation is https://example.com/auth/facebook/callback
The passport.js handler for the https://example.com/auth/facebook/callback route will invoke the callback function that receives the Facebook access token and some user information from Facebook, including the user's email address.
With the email we can locate the user in our database and store the Facebook access token with it.
The last thing you do in the Facebook callback is to redirect back to the rich client application, but this time we need to pass the username and the access token to the client so that it can use them. This can be done in a number of ways. For example, Javascript variables can be added to the page through a server-side template engine, or else a cookie can be returned with this information. (thanks to #RyanKimber for pointing out the security issues with passing this data in the URL, as I initially suggested).
So now we start the single page app one more time, but the client has the username and the access token.
The client application can trigger the "login" event immediately and let the different parts of the application request the information that they need from the web service.
All the requests sent to https://example.com/api will include the Facebook access token for authentication, or the application's own access token generated from Facebook's token via a "get_access_token" function in the REST API.
The non-browser apps have it a bit more difficult here, because OAuth requires a web browser for logging in. To login from a phone or desktop app you will need to start a browser to do the redirect to Facebook, and even worse, you need a way for the browser to pass the Facebook access token back to the application via some mechanism.
I hope this answers most of the questions. Of course you can replace Facebook with Twitter, Google, or any other OAuth based authentication service.
I'd be interested to know if someone has a simpler way to deal with this.
I greatly appreciate #Miguel's explanation with the complete flow in each cases, but I'd like to add some on the Facebook Authentication part.
Facebook provides a Javascript SDK which you can use to get the access token on client-end directly, which is then passed to the server and used to further pull all the user information from Facebook. So you don't need any re-directs basically.
Moreover, you can use the same API end-point for mobile applications as well. Just use the Android / iOS SDK for Facebook, obtain the Facebook access_token on the client end and pass it to the server.
Regarding the stateless nature as explained, when get_access_token is used to generate a token and passed to the client, this token is also stored on the server. So it's as good as a session token and I believe this makes it stateful ?
Just my 2 cents..
Here is an awesome article I found that can help you authenticate with:
Facebook
Twitter
Google
Local Auth
Easy Node Authentication: Setup and Local

Resources