48

I want to build small application. There will be some users. I don't want to make my own user system. I want to integrate my application with oauth/oauth2.0.

There is no problem in integration of my front-end application and oauth 2.0. There are so many helpful articles, how to do this, even on stackoverflow.com. For example this post is very helpful.

But. What should I do after successful authorization on front-end? Of course, I can just have flag on client, which says "okay, mate, user is authenticated", but how I should interact with my backend now? I can not just make some requests. Back-end - some application, which provides API functions. EVERYONE can access this api.

So, I need some auth system anyway between my FE and BE. How this system should work?

ps I have some problems with English and may be I can not just correctly 'ask google' about it. Can you provide correct question, please :) or at least give some articles about my question.

UPD

I am looking for concept. I don't want to find some solution for my current problem. I don't think it is matters which FE and BE I use (anyway I will provide information about it below)

FE and BE will use JSON for communication. FE will make requests, BE will send JSON responses. My application will have this structure (probably):

  • Frontend - probably AngularJS
  • Backend - probably Laravel (laravel will implement logic, also there is database in structure)

Maybe "service provider" like google.com, vk.com, twitter.com etc remembers state of user? And after successful auth on FE, I can just ask about user state from BE?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Sharikov Vladislav
  • 7,049
  • 9
  • 50
  • 87
  • Are you using JSON for communication? Basically it depends on how you have implemented authorisation in the backend. What I would usually be doing is sending the value of the flag as a key-value pair as a part of the JSON data to my backend while hitting the API. I would checking for this key while initiating a session or sending a token string back to the client. – Soumojit Ghosh Nov 22 '15 at 21:20
  • What server side framework are you using? How did you implement the Oauth2 authentication? – Dvir Nov 22 '15 at 21:24
  • @Dvir , is it really matters for solution to my question? I am asking about concept, not some solution for this problem. – Sharikov Vladislav Nov 22 '15 at 21:25
  • I understand you will using javascript at the front-end and php at the backend. No matter what you are using, you will need to send the data to the backend to notify that user has been successfully authenticated. The best way of sending this data would be by adding it to the data with your request. – Soumojit Ghosh Nov 22 '15 at 21:27
  • I'm asking because it sound like you asking what should I do when the user got token right? You actually suppose to add it to the header of the request so the server which is get the request will fetch the token and will know handle the request correspond to the user that sent the request. – Dvir Nov 22 '15 at 21:28
  • @SoumojitGhosh Hm. Yes, but anybody can open some tools, which collect http requests (like fiddler) or any other thinking guy will understand , that I have back-end somewhere. He will make same requests with some additional data in them and he will get restricted data (for him) – Sharikov Vladislav Nov 22 '15 at 21:29
  • @Dvir Actually, SoumojitGhosh suggested same thing. I'd already answered. – Sharikov Vladislav Nov 22 '15 at 21:30
  • That is why, you will be encrypting your data before sending it to the backend. – Soumojit Ghosh Nov 22 '15 at 21:30
  • Sure, I understand, that I must use HTTPS for encryption. But it will be _security throught obscurity_ and this approach is totally bad in this case, I think. Am I right? Hm... Or all services using this approach and I don't need to worry about it? – Sharikov Vladislav Nov 22 '15 at 21:31
  • That's why Oauth added the `refresh_token`, for more secure. – Dvir Nov 22 '15 at 21:32
  • @Dvir Oh. It can be interesting. I will gather some info about it and will update my post after it, if question will be still actual. Its it okay? – Sharikov Vladislav Nov 22 '15 at 21:33
  • Sure. Anyway you will ask the same question as I did when I implemented the Oauth2. If someone will get the refresh_token so what next and bla bla. So the idea that it's still more secure than holding the username and the password on the client. – Dvir Nov 22 '15 at 21:34
  • Https is just a secure channel where your data can't be tampered with. But you will need to encrypt your communication. Kindly check md5 and ssh encryption techniques. – Soumojit Ghosh Nov 22 '15 at 21:34
  • @SoumojitGhosh with fiddler you can get the data before it encrypted and get what ever you want, But you right that is more secure. – Dvir Nov 22 '15 at 21:36
  • Okay :) you say it will be same as sending some token beetween, but it is _a bit more secure_. Looks like, I need to implement 1 more authentification layer by myself. For example, when user is looged in throught OAuth, I will generate some password, based on service provider name, login on this service provider, may be some random data, connected to the user. After this, each time he will log in throught oauth, I will regenerate this password and make some request to log in in backend? – Sharikov Vladislav Nov 22 '15 at 22:15
  • This backend will compare current generated password and password stored in my database and if okay, session will be openeed and user will be able to interact with BE. It is looks like _simple_ authentification. Right? Is it solution? – Sharikov Vladislav Nov 22 '15 at 22:17

6 Answers6

45

We have 3 main security concerns when creating an API.

  1. Authentication: An identify provider like Google is only a partial solution. Because you don't want to prompt the user to login / confirm their identity for each API request, you must implement authentication for subsequent requests yourself. You must store, accessible to backend:

    1. A user's ID. (taken from the identity provider, for example: email)
    2. A user token. (A temporary token that you generate, and can verify from the API code)
  2. Authorization: Your backend must implement rules based on the user ID (that's your own business).

  3. Transport security: HTTPS and expiring cookies are secure and not replayable by others. (HTTPS is encrypting traffic, so defeats man-in-the-middle attacks, and expiring cookies defeats replay attacks later in time)

So your API / backend has a lookup table of emails to random strings. Now, you don't have to expose the user's ID. The token is meaningless and temporary.

Here's how the flow works, in this system:

User-Agent    IdentityProvider (Google/Twitter)   Front-End    Back-End
 |-----------------"https://your.app.com"---------->|
                                                    |---cookies-->|
                                 your backend knows the user or not.
                                       if backend recognizes cookie, 
                          user is authenticated and can use your API

ELSE:

                                             if the user is unknown:
                                                    |<--"unknown"-|
                     |<----"your/login.js"----------+
                "Do you Authorize this app?"
 |<------------------+
 |--------"yes"----->|
                     +----------auth token--------->|
                     |<---------/your/moreinfo.js---|
                     |-------access_token ---------->|
                1. verify access token
                2. save new user info, or update existing user
                3. generate expiring, random string as your own API token
                                                    +----------->|
 |<-------------- set cookie: your API token --------------------|

NOW, the user can directly use your API:

 |--------------- some API request, with cookie ---------------->|
 |<-------------- some reply, depends on your logic, rules ------|

EDIT

Based on discussion - adding that the backend can authenticate a user by verifying the access token with the identity provider:

For example, Google exposes this endpoint to check a token XYZ123:

https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
Jeff Meatball Yang
  • 37,839
  • 27
  • 91
  • 125
  • I have a question about developing 1st part: authentification. As I said, it is not problem to get user id from provider (like Google etc). As you say, I need some user token, that is generated on client and verified by API (backend, server). How exactly this token must be generated on client? How server will verify it? can you provide exact example: first user login from some provider (so server don't know about user) and later logins? It will be great. I understand basic authorization. – Sharikov Vladislav Dec 02 '15 at 07:07
  • 1
    I did not understand one thing. Yes, I have token from google ouath, I have some user id. But my API doesn't know about this user and this token. What about first login? As I think anybody can take my email, take some token from mind, make request and get restricted data. Can you explain it? – Sharikov Vladislav Dec 02 '15 at 07:14
  • The token must be generated by your backend. Study the flow diagram, and you will see the backend GENERATE the token because at the end, it must VALIDATE the token. It should be random: simply generate a random string that is 200 characters long, and save it in some lookup table with the associated user. This is an endpoint like /api/generate_token. That needs to respond with a "Set-Cookie" header with the value of the random string. – Jeff Meatball Yang Dec 02 '15 at 07:15
  • The Google token is a different token. Your API must generate its own tokens too. The frontend must make a request to Google to get a user identifier (email), then POST it to your API (/api/generate_token) which will allow your front-end code to make more requests to your API. – Jeff Meatball Yang Dec 02 '15 at 07:17
  • Okay, so everybody can take some email (not his email), POST it to `/api/generate_token` and get access to restricted data? For example, there is no provider which provide email. Anybody can do it manually. Right? It is not correct. – Sharikov Vladislav Dec 02 '15 at 07:19
  • Now you are asking the right question! You must implement the access rules yourself. Let's say you only allow users with emails from `mycorp.com`. Then, your `/api/generate_token` will simply reject anyone without that email. You can get more information from the identity provider, like what is their Google ID, name, tweet history, etc. Then you write access logic according to that information. Obviously, you want to make sure you get information that can only be gained from a proper login via the identity provider. (and that can include the OAuth access token) – Jeff Meatball Yang Dec 02 '15 at 07:23
  • No, wait :) For example: google oauth2.0. For example, I will reject every request without `email=*@gmail.com`. Ok. But what if somebody will take some `*@gmail.com` address and make request using this email? Access will be granted? I think I need something like password there. Also, I think I need something like simple registration there. Example: I got user id and some string from oauth2.0, made request to /generate_token, if user is not registered, registration process starts and permissions are granted. – Sharikov Vladislav Dec 02 '15 at 07:30
  • On 2nd login, client send user id and some string from oauth20 (which is constant, just my assume, am I right?) and check if they are exist. They are, so permissions are granted. There is another problem : anybody can take some email, take some token from their mind (like abcd) and request /generate_token. System will register new user with this email. – Sharikov Vladislav Dec 02 '15 at 07:31
  • 1
    I updated my answer. Everywhere you see email, you can replace with `access_token`. This is verifiable by your backend. I misunderstood what you wanted to secure. – Jeff Meatball Yang Dec 02 '15 at 07:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/96766/discussion-between-sharikov-vladislav-and-jeff-meatball-yang). – Sharikov Vladislav Dec 02 '15 at 07:32
  • Aaaaaaaaaaaah. that is the point. So I send user id, I send provider identifier (google, twitter, vk etc) and I send some token from oauth20 (I just got it on client) and API check if this token is okay through google api (or twiter, or vk etc). Right? On 2nd login I will do same etc. Right? I don't see any strange places there. I need provider id to understand what api I should call to check token from API: twitter, google etc. – Sharikov Vladislav Dec 02 '15 at 07:35
41

I read through all the answers very carefully, and more than half the people who responded are missing the question completely. OP is asking for the INITIAL connection between FE & BE, after the OAuth token has been issued by the Service Provider.

How does your backend know that the OAuth token is valid? Well keep in mind that your BE can send a request to the Service Provider & confirm the validity of the OAuth token, which was first received by your FE. This OAuth key can be decrypted by the Service Provider only because only they have the secret key. Once they decrypt the key, they usually will respond with information such as username, email and such.

In summary:

Your FE receives OAuth token from Service Provider after user gives authorization. FE passes OAuth token to BE. BE sends OAuth token to Service Provider to validate the OAuth token. Service Provider responds to BE with username/email information. You can then use the username/email to create an account.

Then after your BE creates the account, your BE should generate its own implementation of an OAuth token. Then you send your FE this OAuth token, and on every request, your FE would send this token in the header to your BE. Since only your BE has the secret key to validate this token, your application will be very safe. You could even refresh your BE's OAuth token on every request, giving your FE a new key each time. In case someone steals the OAuth token from your FE, that token would be quickly invalidated, since your BE would have already created a new OAuth token for your FE.

There's more info on how your BE can validate the OAuth token. How to validate an OAuth 2.0 access token for a resource server?

Community
  • 1
  • 1
Webber
  • 941
  • 11
  • 26
  • Nice answer. Imagine that my BE does not impements own OAuth token. So I have to send token from frontend in everyrequest and backend will request Service Provider if token is valid _each_ time, correct? – Sharikov Vladislav May 09 '17 at 21:34
  • Ok, Imagine I implement my own OAuth token system. I will have some place, where I will store this token. Client will make requests and send some token. BE check if token exists in BE storage and if yes it will respond correctly, otherwise it will return 403 for example. Correct? – Sharikov Vladislav May 09 '17 at 21:38
  • 1
    This is the best answer, it's very clean and correct workflow, thanks. – julian salas Jul 03 '17 at 06:57
  • When BE generates a new token and return it to FE, it's valid for only one request. What if someone steels the new token shared with FE before that one request, and manipulate the request while calling BE. How to handle such case ? Can FE hide the token while receiving in response OR passing in request ? – Nakul Goyal Nov 29 '21 at 09:55
5

let's use OAuth concept to begin,FE here is Client , BE here is Resource Server.

  • Since your client already authorized, Authorization server should grant Access token to the client.
  • Client make request to the resource server with the Access token
  • Resource server validate the Access token, if valid, handle the request.

You may ask, what is the Access token, Access token was issued by authorization server, grant to client, and recognized by resource server.

Access token is a string indicate the authorization information(e.g. user info, permission scope, expires time...).

Access token may encrypted for security, and you should make sure resource server can decrypt it.

for more details, please read OAuth2.0 specification https://www.rfc-editor.org/rfc/rfc6749.

Community
  • 1
  • 1
lessisawesome
  • 1,313
  • 1
  • 12
  • 14
3

Well you don'y need User-System on your Front End side. The front end is just a way to interact with your server and ask for token by valid user and password.

Your server supposed to manage users and the permissions.

User login scenario

User asking for token by entering his username and password. The server-API accept the request because it's anonymous method (everyone can call this method without care if he's logged in or not.

The server check the DB (Or some storage) and compare the user details to the details he has. In case that the details matches, the server will return token to the user.

From now, the user should set this token with any request so the server will recognize the user. The token actually hold the user roles, timestamp, etc...

When the user request for data by API, it fetch the user token from the header, and check if the user is allowed to access that method.

That's how it works in generally.

I based on .NET in my answer. But the most of the BE libaries works like that.

Dvir
  • 3,287
  • 1
  • 21
  • 33
  • I understand all, that you said. I didn't ask about how common user system should work. I understand it perfectly. My question was about how to deal with OAuth 2.0, front end and back end. I logged in with some service (Google) on FE successfully, now I need way to interact with my BE. That was the question. – Sharikov Vladislav Nov 26 '15 at 00:48
  • @SharikovVladislav, after you authorized, you can send http requests with Authorization Header with the value of the access token issued by authorization server(google oauth server). – lessisawesome Dec 02 '15 at 03:51
  • @lessisawesome yes, but what about first login? Okay, I have token from google oauth, but my API don't know anything about this token. So I need something like registration. Yes, I have user id (i.e. email), some auth token. How exactly I should interact with my API now? just send email and token? so _everybody_ can take my email, call some request and get access to restricted data? – Sharikov Vladislav Dec 02 '15 at 07:11
  • 1
    There is some connection between you API server(Resource server) and Authorization Server.For example, Auth server put the user identity and authorization info into a token string using encryption algorithm,and resource server should know the algorithm in order to decrypt the token. – lessisawesome Dec 02 '15 at 07:51
  • @SharikovVladislav if use google login, the access token can only used to request resource from google. It doesn't make any sense to your own api server. – lessisawesome Dec 02 '15 at 07:56
2

As am doing a project for SSO and based on my understanding to your question, I can suggest that you create an end-point in your back-end to generate sessions, once the client -frontend- has successfully been authorized by the account owner, and got the user information from the provider, you post that information to the back-end endpoint, the back-end endpoint generates a session and stores that information, and send back the session ID -frequently named jSessionId- with a cookie back to the client -frontend- so the browser can save it for you and every request after that to the back-end considered an authenticated user.

to logout, simply create another endpoint in the back-end to accepts a session ID so the back-end can remove it.

I hope this be helpful for you.

Abdullah Shahin
  • 1,002
  • 15
  • 19
  • Yes, but what about the defence? Everybody can send some user email for example and get access to user data. Right? Or should I create registration also and use some static information from provider as password? So I will register user and the log on with his credentials. – Sharikov Vladislav Dec 01 '15 at 20:53
1

You need to store the token in the state of your app and then pass it to the backend with each request. Passing to backend can be done in headers, cookies or as params - depends on how backend is implemented.

Follow the code to see a good example of all the pieces in action (not my code) This example sets the Authorization: Bearer TOKEN header https://github.com/cornflourblue/angular-registration-login-example

Andrei R
  • 4,904
  • 5
  • 25
  • 26