Django Rest Framework Session vs Token Authentication - authentication

I'm using DRF, and I've enabled Session Authentication so that I can view the browseable API in my browser. In my mobile app, i'm using token authentication. I'm just curious, how does session authentication differ from token authentication in this context? It seems to me that they are more or less the same because with session based auth, a session id instead of a token id is stored in a cookie and used in the same way. Can anybody explain it better?

Sessions and cookies are mainly meant for browsers where the browser will take care of sending the cookie with every request to the server. This why the CSRF protection is only enabled by default for session authentication. On the other hand, token authentication will most probably used with non-browser clients where it stores the auth token and send it with each request in header. This token is not necessarily obtained by exchanging the credentials for a token similar to what happens in session authentication. There can be a use case where an admin generates these tokens and hands it to some other system client that will invoke your API, and clearly this client does not have to have a username and password to exchange it for a token.

Related

ID token usage when using "Log in with Google" in a mobile app

Suppose that I have a mobile app with a frontend and a backend server.
My understanding is that -- when a user logs in the app with "Login with google", the frontend sends a request to the google auth server, and gets back an ID token. The documentation says that the frontend can then send the token to the backend server to establish a session. I imagine that means the token can be used in session-based authentication?
If I were to use token-based authentication (as opposed to session-based), do I just attach the ID token in every server request, and have the backend verifies it each time when processing a request? this page suggests the ID token should not be sent to the backend API. Which leaves me wonder what the correct procedure is for token-based authentication when using log in with Google.
So my question is: Does my server need to create an access token from the ID token from Google, and send it to the frontend, so the frontend can attach that access token in the API requests for authentication?
Thanks
Login with Google is an identity provider (IDP) operation. A full OAuth solution, including an authorization server (AS) looks like this:
Mobile app uses system browser to redirect to AS
AS returns a redirect response to the system browser, which routes to the IDP
User signs in at the IDP
IDP returns an authorization code to AS
AS swaps it for IDP tokens and carries out validations
AS issues a set of tokens to the app. This includes an access token (AT) with whatever scopes and claims are needed for business authorization to work.
Mobile app sends AT in API requests
API authorizes using scopes and claims from the access token
So ideally plug in an authorization server, to get this out-of-the-box behaviour. Another option is to implement your own token service, and issue your own tokens. That is less recommended though, since it requires more detailed understanding of the underlying security.

When an Oauth provider is used to delegate authentication, then does the appserver return any token to the caller?

In Oauth and Openidconnect, the appserver endpoint invocation starts the Oauth flow and the app server gets the token from the auth server and is able to pass the token to resource server to access resources (delegation) on behalf of the resource owner.
The token exchange happens between the app server and resource server, and the token never arrives at the end users browser.
I'm working on a web api (aka app server) that will be consumed by a mobile app. There is no other server involved. Presently the login endpoint returns a signed JWT token to the user if correct credentials are supplied (validate against the db). User places this token in the header of the subsequent request.
Assuming I don't want to have a user db and validate logins, and instead delegate the auth check to another service like azure b2c or firebase (that use the Oauth), then I assume the flow is like given below:
Api registered the firebase/azure b2c (let's call this the provier) clientid, secret.
User invokes login endpoint of my api
The api invokes the provider's Oauth flow.
User gets popup to authenticate with the provider.
Eventually the provider will send the token (containing the claim like username) to the api (aka app server)
Does the user get back any token? Otherwise, when the user makes subsequent endpoint calls, then how is the endpoint able to identify who is this user and whether he is already authenticated?
Although it is okay to send back the access token to the user , but from the security best practise 's point of view , it is better not to do it which I quote the reasons as follow from this:
Because of the issues outlined above, the best security recommendation
for an SPA is to avoid keeping tokens in the browser at all. This can
be achieved with the help of a lightweight back-end component, often
described as a Backend-For-Frontend.
The backend component can then be configured as a confidential OAuth
client and used to keep tokens away from the browser. It can either be
stateful and keep tokens in custom storage, or stateless and store the
tokens in encrypted HTTP-only, same-site cookies. Whichever variant is
chosen, the backend component creates a session for the SPA, using
HTTP-only, secure, same-site cookies, thus enabling a high level of
security. Such cookies cannot be read by scripts and are limited to
the domain of the SPA. When combined with strict Content Security
Policy headers, such architecture can provide a robust protection
against stealing tokens
Also from here ,they suggest for mobile app 's OAuth2 best practise , it should perform the OAuth flow inside a system browser component.

How to authenticate SPA users using oAuth2?

Alright, I've spent several days looking for a proper solution on how to properly authenticate users when working with SPAs.
I have my own website.
I have my own API.
I have my own Single Page Application.
I have my own database of users.
The Goal: I need to get an access_token by providing a username and a password.
I looked at OAuth2 Implicit Grant, but it requires users to Approve/Decline the app after successful authentication. It doesn't work in my case since I own both the app and the API.
I looked at OAuth2 Password Grant, which is not perfect since I need to expose client_id/client_secret.
The reason I'm looking at OAuth2 is because the API will eventually be public.
Is there a standard way of doing this? My current options:
Forget about OAuth2 and manually generate access_token when user POSTs username/password (in this case I'd have to introduce OAuth2 when API goes public)
Use OAuth2 Password Grant and inject client_id/client_secret on the server, so just to keep client app very simple (also avoid all of those dev/staging/prod client_id/client_secret pairs)
Implicit Grant
You are right that Implicit grant type does not look appropriate. But I think your reason for not favoring it is incorrect because the approval step is not mandatory and in Spring OAuth 2 implementation (I don't know which implementation you are using) you can configure the Authorization server to auto approve authorization requests so that the approval step is skipped.
The reasons I think the "Implicit flow" is not suitable are
​The client authentication step by providing client secret and authorization code is missing. So less security.
The access token is sent back as a URL fragment (so that the token doesn't go to the server) which will continue to stay in browser history
If XSS attack occurs, the malicious script can very well send the token to the remote server
Resource Owner Password Credentials Grant
If the authorization server and the resource server are the same, I think this is a quick way of getting up and running. RFC 6749 in Section 4.3.2 says:
If the client type is confidential or the client was issued client credentials (or assigned other authentication requirements), the client MUST authenticate with the authorization server as described in Section 3.2.1.
This means that the client authentication with client secret is not mandatory here. Now, for authorization code grant type, we need the client secret because the user provides his/her credentials directly to the authorization server and then when the client requests for the access token, it doesn;t have anything else other than the client secret to prove to the authorization server that this is a genuine request.
But in case of resource owner password credential grant type, the user has provided its credentials to the client itself and the client will then send these same user credentials for requesting access token. Therefore, the access-token request can be authenticated with the user credentials only and if we don't provide a client secret here, I don't think we are losing anything in terms of security.
So, you can definitely use password credential grant type in your SPA.
Authorization Code Grant
I think this should be the preferred option provided the client secret is not stored in the browser. After user authentication (and optionally user approval), the authorization server can redirect the browser to a server side endpoint with the authorization code in the URL. The server side end point will the request for the access token using the authorization code, client id and client secret (which is stored in the server side only). Once the access token is available, the server side endpoint can redirect (HTTP response code 302) the user to the SPA URL with appropriate cookies for CSRF protection and access token. Thus we are not storing the client secret in the browser.
By using authorization code grant type, you are basically making the solution more secured and generic. In future, if you want to do a single sign-on with a different SPA, you can do that easily by reusing the same authorization server with its integration with the authentication database (preferably an LDAP server).
For further details, refer to my StackOverflow answer here.
Building off what has been said already, I would recommend the 'Authorization Code Grant' but with the addition of the PKCE (Proof Key for Code Exchange / 'pixie') extension - for added security, regardless of whether you're implementing a 'public' or 'confidential' type client.
With PKCE, you don't need a client-secret for public clients (/it's kind of like generating a temporary client-secret at the very outset/beginning of each authentication attempt/instance - although even with PKCE for confidential clients you should ideally still use a client secret).

JWT token for multiple websites

How can I have a single JWT token be shared among multiple websites. I assume that the first thing would be to have the same secret on all websites.
If user logs in on site A and a token is generated I want to use the same token for website B on a totally diferent domain.
Can it be done?
What you want can be done, but not with a single JWT token. A JWT token is intended for a certain service or application indicated by the audience (aud) claim. You cannot use the same token for another application or service.
What typically happens to make your SSO scenario work, it that the user logs in to the token issuing (authorization) server. As long as that session is valid, the user can acquire tokens for all applications the server can issue tokens for.
So, when the user logs in to the first application, the authorization server sets a cookie to establish a session. When the user navigates to the second application, the application redirects him/her to the authorization server for authentication. The authorization detects the session cookie and does not prompt to user to log in again, but issues a new JWT token for the second application.

How to get a JWT?

When reading about securing an app with JWTs, it is often said that the client initially gets a token from the server and then sends this token along with every request to the API.
This approach works great, once you have a token. As far as I can see, the default way of transferring a token is using an HTTP header, namely Authentication with Bearer as the prefix of the token as value.
But - is there also a default way of how to get the token initially? In samples you often see that this is just a simple request to and HTTP endpoint, that then returns JSON. But I was wondering whether there is something more of a standard workflow that e.g. describes what should be the name of this endpoint, as in OAuth2?
Any hints?
JWT is a token format which is used in security protocols like OAuth2 and OpenID Connect.
How to get the token from the authorization server depends on the grant flow you are using.
There are 4 grant flows defined in OAuth 2.0 that are intended for different clients and uses.
Authorization code grant
This grant is intended for web applications. The user's browser is redirected (HTTP 302) to the authorization server. The authorization server takes care of authenticating the user (via username/password, smartcard, 2-factor auth whatever).
The authorization server then redirect the browser back to a preregistered endpoint in the web application with a code. The web application then uses it's own credentials (client id and client secret) and the authorization code to request an access token from the authorization server.
The authorization server returns an access token and a refresh token to the web application. Note that the browser (untrusted) never sees the access token. Only the web application (trusted) has access to the access token and refresh token.
This grant is difficult to use from other clients than web applications as it's based on HTTP redirection.
Implicit grant
This grant is used for untrusted clients like JavaScript applications or 3rd party mobile clients (the ones you download from the app-store).
It also redirects a browser (or browser control) to the authorization server, but instead of returning a code to the browser after successful authentication, it returns an access token directly. Because the client is not trusted, the grant does not return a refresh token. The access token needs to be stored somewhere and is vulnerable to XSS attacks.
Even though you do not get a refresh token, some implementations do provide a way to get a new access token by communicating to the authorization server in a hidden IFRAME and using cookies to authenticate with the authorization server itself.
Resource Owner Password Credentials grant
This grant is for trusted clients, for example a desktop application or a first party mobile app with secure storage capabilities. The client application asks the user (the resource owner) for their username/password and then sends this to the authorization server to acquire an access token and refresh token.
Once the client has the access token, it can discard the password as it can use the refresh tokens to get new access tokens. This makes it more secure than basic authentication.
This grant does not depend on browser redirects and can be easily used from any application that can execute HTTP requests.
Client Credentials grant
This grant is meant to authenticate the client (application) instead of the user of the client.
In this case, the client submits its client id and secret directly to the authorization server to acquire an access and refresh token.
So basically the first two grants depend on browser-like capabilities (HTTP redirects, HTML login pages), where the other two grants only need an HTTP stack to communicate with the authorization server.
Every OAuth2 server has its own endpoints. The client can discover the name of relevant endpoints using discovery protocols like http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata.