Elixir Phoenix Absinthe GraphQL API authentication in both web and mobile app's - graphql

I'm working on an Absinthe GraphQL API for my app. I'm still learning the procedure(so please go easy on me).
I've a Absinthe/GraphQL MyAppWeb.schema.ex file in which I use for my queries and mutations. My question is how do I use this API for authenticating the user on both Mobile and Web app?
How do set a cookie(httpOnly & secure) in my web app and access/refresh tokens in a single Absinthe API to serve my website and mobile app. Basically what I'm trying to learn is how do I authenticate the user based on specific platform.
If my question sounds bit confusing, I would be happy to provide more information related to my question. I would really be grateful if someone could explain the procedure, I've been very stuck on this for a while.

I would avoid using authentication mechanisms provided by absinthe(if there are any). Depending on what front-end you are using, I would go with JSON API authentication. The flow on server goes the following way:
Create a endpoint for login that will receive a user and password and will return a refresh token.
Create a endpoint for exchanging refresh token for access token.
Use a library like guardian to generate your refresh/access tokens.
Create a phoenix plug for authentication that will check your tokens, guardian has some built-in plugs for this.
Now on device you have to implement:
Ability to save refresh and access token on device.
Have a global handler for injecting access token on authorized requests.
Have a global handler for case when access token is expired. (you usually check if your request returns Unauthorized, then you should request a new access token from the server using your refresh token)
This seems like a crude implementation, however I would advise in implementing your system instead of using a black box library that you have no idea how it works under the hood.

Related

How to access a secured API in the frontend?

There is a lot of good content on the internet that explains how to secure a Spring API with Keycloak: Create a Client that represents the API Service in Keycloak and use a link like the one below to get the access and refresh token:
<Domain>/auth/realms/<realm>/protocol/openid-connect/auth/{some parameters}
This yields both tokens. So far so good.
Now, however, I am not sure how the flow for the frontend accessing the API should look like.
Should the frontend directly access this endpoint and, therefore, obtain the access and refresh token? That would mean that the API can only have the access-type public because there is no way to store the client (the API) secret securely.
Or should there be a third server that somehow stores the refresh token for each user, that the user can call if his access token is no longer valid. This server would then use the client's refresh token (and the client secret that could be stored securely, since it would be in the backend) to get a new access token from Keycloak and would forward it to the user.
I guess the main question that I am asking is, whether the client/user should get the refresh token.
If one needs to implement a logic according to the second option, I would be interested in a link or description of how something like this can be done in Spring.
I think, in either case you need to use the Authorization Code Flow. The implicit flow, which was recommended for SPAs (frontends without a backend server) in former versions of OAuth2 must not be used anymore.
The best option is to have a backend server, so the user retrieves the auth code via redirection and the backend server exchanges this auth code with the access and refresh tokens (and keep them without forwarding them to the frontend).
If there is no backend in place and your frontend needs to retrieve and hold the tokens directly, I would recommend to use the Authorization Code Flow with a public client and the PKCE extension (which - put simply - ensures that the entity asking for the auth code is the same as the entity asking for the tokens and that the auth code was not stolen and used by a foreign entity). There are several sources with more detailed explanations, which might help you, for example: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce
Hope this helps you with your architectural considerations.

After fetching the access token to perform API requests on user's behalf, whats the "proper" way to keep the user session and token connected?

I'm currently developing an identity 4 server, an API protected by scopes defined on the identity server and the mobile app server which will consume information from the API.
By now I already got a good grasp of how to use the authorization and access tokens and how to perform the correct flows, however I got into a dilemma when I started looking at the user session between the mobile app and server. After receiving the access and identity token, which basically serves as confirmation of user login/authorization, which would be the "proper" way to store it and keep the session alive with the app?
Initially I thought of using using cookies, but was told it doesn't work well with mobile apps (I barely know anything about android/ios), to which I followed by considering the creation of JWT on the server, which seemed wrong considering the existence of the identity server that was already producing tokens. And with this, how would I related the session to the access token to perform the API requests?
TLDR:
After fetching access and id token for the client, what "proper"
methods are there to keep sessions alive between client and mobile app?
How to relate the session to the access token to use when API requests are necessary?
Thanks !
For a modern native mobile app I'd suggest using the authorization_code flow (via the default browser on the device) with PKCE and storing a refresh token in the secure enclave of the device. This can then be protected by built in PIN or biometric features.
With that (carefully protected) refresh token you can maintain a long lived session without the need to do front channel (i.e. web browser) interactions with the OIDC service.

What to return after login via API?

I'm creating an API server which will be consumed by a mobile app that I will work on later. I have yet to see any reference of API best practices related to user flow and returned data even after searching for several hours.
My question is whether the login response of an API should return the a personal access token with the refresh token along with the user info? Or should I just return the token and make another API call for getting the user info.
I could just do what I have in mind but I'm trying to learn the best practices so that I don't have to adjust a lot of things later.
I need suggestions as well as good references related to my question.
Thank you.
It depends on what you are using for your authentication. If you are using libraries like Laravel Passport or JWT, you can have the token endpoint which returns the access token, refresh token, validity period and the token type (Bearer). You can then have an authenticated endpoint which will be used to get a user's profile based of the token passed in the request header.
However, if you go through the documentation for those libraries, in most there is an allowance to manually generate a token. You can use this in a custom endpoint that will return the token as well as the user profile Passport Manually Generate Token.
If you are using JWT, you can also embed a few user properties in the token itself. The client can the get the profile info from the JWT itself without having to make a round trip to the server. Passport ADD Profile to JWT
If you have a custom way in which you are handling authentication, you can pass the token as well as the user profile in the same response.
In the end, it's up to you to decide what suits you best.
Have you looked at OpenID Connect? It's another layer on top of OAuth 2.0 and provides user authentication (OAuth 2.0 does not cover authentication, it just assumes it happens) and ways to find information about the current user.
It has the concept of an ID_token, in addition to the OAuth access token, and also provides a /userinfo endpoint to retrieve information about the user.
You could put user information in your access token, but security best practice is to NOT allow your access token to be accessible from JavaScript (i.e. use HTTP_ONLY cookies to store your access token).

Securing web app and api using OpenID Connect

I don't want to roll my own security anymore and am looking at using OpenID Connect with my c# API and AngularJS app. I can get all that to work just fine. However, my brain cannot seem to understand how to secure my API correctly for both use cases:
Use Case 1: AngularJS SPA
My AngularJS app connects to my API and sends a bearer token identifying the user and includes user claims. This one is easy and there is tons of documentation on it.
Use Case 2: API to API
Some customers want to access my API directly instead of going through my AngularJS app. In this case, I thought I could use a Client ID/Secret for toen-based authentication which is great except then I know nothing about the user that's using the client id/secret. There could be 10 users using the same custom API that is calling my API. How do I get user info via the API call? I've seen others use API keys that they then lookup the user and create a JWT but I thought there might be an easier way. Any ideas?
The whole point of API to API authentication is that there is no user context. Or well, the user in that case is the machine trying to access your API. You would then need to design your authorization logic around that and implement scope based permissions. Alternatively, your options are to use api keys as you mentioned or if you want OAuth protocol with user context in the api to api scenario - then ResourceOwnerCredentials flow is an option.
API to API communcation
You can use Client Credentials Grant defined through OAuth 2.0. This won't require you to have end user credentials. Now this won't be OpenID Connect. OpenID Connect require the involvement of an end user and bound to authentication. OAuth 2.0 on the other hand is about authorization, checking whether the entity can access the resource.
With Client Credential Grant, your identity server will issue tokens for a specific client. So one of your API becomes the client (resource consumer). From request handling API endpoint, you can accept valid tokens and respond back with resource.
If you require fine grained access control from request handling API, you will require to use token introspection to identify to whom this token was issued. In this case, it will be identification of specific client identity and execute a logic on top of it. You can check the token introspection response to identify such details.
Alternatively, access tokens can be come in form of a JWT. If this is the case, they can be considered as self contained tokens so validation is straightforward.

API Authentication and use of OAuth2

I’m trying to get my head around how I would introduce token-based (key-based?) authentication to a web API (currently looking at Sinatra, but maybe Rails too) that would be used by a mobile client and how OAuth would fit into the picture.
So, let’s say I want to create a web service that uses Facebook for authentication and grabbing basic user data. Here, my API would be a client to Facebook’s OAuth Server, requesting an access token upon a user’s successful login to Facebook. This would then grant me access to the user’s data which I would use to create an entry in my database, storing this user-specific token with any other application information I would like linked to them.
I think I got that part right so far, but here’s where I’m a bit confused.
I think that my API would also need some form of API key to grant access to a mobile user, since I wouldn’t want to transmit and store the Facebook key on their device. Would I have to have a separate store of keys which I provide to the client to access my service? Are there any ‘best practice’ ways of doing this?
Would I have to have a separate store of keys which I provide to the client to access my service?
yes.
Are there any ‘best practice’ ways of doing this?
The simplest way would be to generate a separate authentication token on every User creation and expose that to the mobile client. Then send it with every subsequent request header.
Devise provides a simple example how to achieve that. You don't need devise for that, just provide some token generation mechanism.
#Devise.friendly_token
def self.friendly_token
SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
end
This mechanism can be extended to provide more security in following ways
Being an oauth2 provider itself.
On successfull login with facebook, you would generate an :authorization_code which the client can exchange for your own Oauth2 Bearer or MAC token within a next step. Then you can send your own Oauth2 token with every request for user authentication.
See rack-oauth2
Implement HMAC token encryption.
Generate and expose a secret_key to every client after singning in. Use this secret to sign messages along with a unique client id. The server can then lookup the secret_key for the specific client_id and verify the message.
See api-auth

Resources