Search code examples
authenticationoauth-2.0credentialsapi-designuser-accounts

Consuming own API for web app - Authentication process with OAuth2


Overview

I am currently in the process of creating an API for an image sharing app that will run on the web and sometime in the future, on mobile. I understood the logical parts of API building, but I'm still struggling to meet my own requirements for the authentication part.

So, my API must be accessible to the world: those with guest access (non logged in people can upload, for example), and also to registered users. So when a registered user uploads, I obviously want the user information to be sent along with the request and to attach that user information to the uploaded image via foreign keys in my database.


Authentication via OAuth2 - Implementation

I have understood that OAuth2 is the way to go when it comes to API authentication, so I am going to implement this one, but I'm really struggling to wrap my head around on how to handle my situation. I thought of using the client credentials grant and generating only one set of credentials for my web app, and having it send requests to the API with its client secret to obtain the access token and let users do stuff. The user registration process itself would be handled with this grant.

But what about when the user is registered and logged in? How do I handle authentication now? Would this require another grant to take over? I was thinking of doing some authorization process during user signin, to generate a new access token. Is this approach wrong?


What I need help with

I need your input on how to handle the authentication flow correctly for my case. This two-way authentication process might not be what I need, but it is the way I've understood it. I would highly appreciate your support.


Solution

  • iandayman's answer has lots of good information, but I think a narrower more specific answer might help you.

    So for starters, the client credentials grant is not for you. If we look at the OAuth2 spec, the client credentials grant is for

    when the authorization scope is limited to the protected resources under the control of the client ... when the client is acting on its own behalf

    This is not right for you for two reasons.
    Firstly there are no protected resources under the control of your client. All resources you are accessing are either unprotected (non-logged in people uploading) or are under the control of an end user. Further, you cannot keep secrets (such as the client secret) in the browser; any user of your application could just use the developer tools of the browser to view and compromise the secret.
    Secondly, as I mentioned, the client is never acting on it's own behalf. It's always acting on behalf of a user who may or may not be logged in.

    You want the resource owner password credentials grant.
    When a user is not logged in (like you mentioned for uploads) you just have no authorization. When a user logs in, you send their credentials to the authorization server. If the password matches the username, the authorization server makes a token and persists a mapping from that token to the user and returns the token. Then every time your client makes another request for a logged in user, you put that token in the Authorization header. On the back end you say "if there is a token in the authorization header, find out which user it corresponds to, and associate them with this upload (or check if they're allowed to upload at all)".

    How does user registration work? Simple, you post some user object like

    name: jim beam
    username: jimb
    password: correct horse battery staple
    

    to your user creation endpoint (POST /users or something). You generate a salt and hash the password, and then store the user's information along with the salt and hash in the database. There is no authorization on this endpoint whatsoever.

    Hopefully this is more what you are looking for.