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.
Related
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.
I know how OAuth2 and OpenID Connect works. But there is still some confusion bothering me.
We develop our own Auth Server, service API and mobile app. So, the client app is trusted and we use "password" grant type. The app user repository follows the same user database in auth server.
Our customers login to the app by username/password. The app then submits the user credential to the Auth Server token endpoint, which will return the (bearer) access token and ID token (JWT) to the client.
The ID token contains basic user information so that the app can greet user like "Welcome Tony Stark!".
The access token can be used to access API (e.g. update user profile).
OAuth by design is not a tool for authentication. Ref: https://www.scottbrady91.com/OAuth/OAuth-is-Not-Authentication
My questions are
1) Do we need to verify the signature of the ID token if the client only is only interested to get the user information? Also note that the ID token is coming from the token endpoint via https connection.
2) Let's forget about the ID token. Can we treat the user has passed the authentication check (i.e. login success) if the client obtains an access token from the Auth Server? This flow is very similar to simple password login without OAuth.
3) The client can access protected APIs with the access token. Without access token, the client can only invoke some public APIs. Is it equivalent to what can be done with and without login? It seems the access token can be treated as "login session cookie".
4) There is no 3rd party involvement in my case. Everything (client, auth server, service API) is developed and owned by the same organization. Does it still make sense to use OAuth?
Typically a mobile app is considered a public client. Unless you're limiting who has access to the mobile app, it can't be considered trusted as someone could mess with the app outside of your control even if you developed it.
Also, the resource credentials grant type is generally not a good idea.
One thing is that the OpenID Connect spec requires authorization code, id token, or a hybrid flow:
Authentication can follow one of three paths: the Authorization Code
Flow (response_type=code), the Implicit Flow (response_type=id_token
token or response_type=id_token), or the Hybrid Flow (using other
Response Type values defined in OAuth 2.0 Multiple Response Type
Encoding Practices [OAuth.Responses]).
Some other reasons:
Why the Resource Owner Password Credentials Grant Type is not Authentication nor Suitable for Modern Applications
The OpenID Connect RFC says you MUST verify the ID token:
When using the Implicit Flow, the contents of the ID Token MUST be validated in the same manner as for the Authorization Code Flow, as defined in Section 3.1.3.7, with the exception of the differences specified in this section.
Although, you may qualify for this exception from 3.1.3.7 if using TLS:
If the ID Token is received via direct communication between the Client and the Token Endpoint (which it is in this flow), the TLS server validation MAY be used to validate the issuer in place of checking the token signature. The Client MUST validate the signature of all other ID Tokens according to JWS [JWS] using the algorithm specified in the JWT alg Header Parameter. The Client MUST use the keys provided by the Issuer.
If you're able to trust the client, and the user/pass check you've implemented, then you should be able to trust that an access token has been granted to an authenticated identity according to the OAuth 2.0 spec.
The access token in OAuth 2.0 also contains scopes and should limit what can be done with that access token. A login without OAuth doesn't necessarily.
It's a good idea to use OAuth to protect the credentials of the resource owner. If you were to use the resource owner credentials grant type, this still provides some benefits as the user could enter the password only when the client doesn't have a valid access token, ie, the user can enter her password once for an access token and validate the user using that instead of entering the password again or storing it somewhere.
Even though this grant type requires direct client access to the
resource owner credentials, the resource owner credentials are used
for a single request and are exchanged for an access token. This
grant type can eliminate the need for the client to store the
resource owner credentials for future use, by exchanging the
credentials with a long-lived access token or refresh token.
OAuth 2.0 RFC6749
1) Do we need to verify the signature of the ID token if the client
only is only interested to get the user information? Also note that
the ID token is coming from the token endpoint via https connection.
YES.
2) Let's forget about the ID token. Can we treat the user has passed
the authentication check (i.e. login success) if the client obtains an
access token from the Auth Server? This flow is very similar to simple
password login without OAuth.
If I understand the premise. Yes..There is no requirement for using the ID Token.
3) The client can access protected APIs with the access token. Without
access token, the client can only invoke some public APIs. Is it
equivalent to what can be done with and without login? It seems the
access token can be treated as "login session cookie".
The access token is a access (like a key) that for the OAuth Client to use that was delegated permissions from the resource owner.
4) There is no 3rd party involvement in my case. Everything (client,
auth server, service API) is developed and owned by the same
organization. Does it still make sense to use OAuth?
Yes. OAuth and OpenID Connect are used by many, many organizations and is a test solution.
You should not try to re-invent the "wheel". Use known trusted libraries for Authentication, Authorization and cryptographic operations. OpenID Connect has some certified Implementations
One of a vendor API documentation mentions that their API calls require to use HTTP Basic Authentication scheme, i.e. user:password Base64 encoded but, their token API (Login equivalent) documentation mentions that "..this service implements OAuth 2.0 - Resource Owner Password & Credential Grant"
Isn't HTTP Basic Authentication different from OAuth ?
Yes, HTTP Basic Authentication different from OAuth 2.0. However, the Resource Owner Password Credentials Grant utilizes Basic Authentication Scheme within the Authorization Request for the Client's credentials as described with section 4.3.1. Authorization Request and Response
The Resource Owner Password Credentials Grant is typically used to convert legacy systems to OAuth 2.0 and no more secure than Basic Authentication Scheme.
Resource Owner Password Credentials Grant is intended to be used when no other Grant Types are available and ONLY when there is a high degree of trust between the Resource Owner and the OAuth Client .
Yes, they both are different.
Http Basic : This is for authentication and user credentials are encoded then passed in HTTP header to the client server.
Basic example for HTTP Basic : Just like traditional web application which asked user to provide credentials and these credentials sent to server in HTTP header. Later server utilize those credentials to authenticate the user.
OAuth 2 : This is for authorization, here the client server required authorization of user data(resource owner) from authorization server.
Basic example for OAuth 2 : Let say there is a online game application running on a server, the user accessed the application which starts loading into user's browser. Now that application asking grants from user to post data about games on his Facebook account. Here user authorize his that application to access his Facebook posts through OAuth Standard. Refer the internal mechanism https://www.rfc-editor.org/rfc/rfc6749
Basic access authentication usage is comparable to OAuth 2.0 Client Credentials Grant Type.
A session can be created using Basic Authentication and services can be accessed using a sessionid in a stateful environment.
But if you do not want to use the session due to session limitations or stateless services, you can use the OAuth 2.0 Client Credentials Grant Type instead, which creates a token instead of session and sessionid. This token provides access to the services.
HTTP basic access authentication:
This is the simpler method for meeting the requirements to access a web service. It is simple because it doesn’t require any of the usual processes in a credentials system: cookies, session IDs or access pages. The whole HTTP basic authentication process is based on standard fields in the HTTP header. Thus, it avoids handshaking: the automated process by which two entities establish authenticated communication before starting normal communication via the established channel. This means equipment can communicate with an external device only if there is successful authentication; otherwise, the communication channel is not created. The connection via modem would fail, for example. The secure development of the basic HTTP access authentication method is HTTPs.
To prevent the basic HTTP access authentication method causing the browser to launch a username and password request for each access, the browser must store this information in the cache for a prudent length of time that doesn’t reduce security excessively. These security credentials are usually stored for 15 minutes.
What is this basic HTTP access authentication method like in the real world?
The access credential provided to third-party developers who want to connect to a mobile API is a totally secret alphanumerical ID.
This alphanumerical API key is stored in a secure space on the server.
The developer making requests for a particular service contained in this API should place this secret ID within the HTTP authorization header along with the word Basic. The two elements together allow the server to recognize the alphanumerical credential and provide access.
GET /private/index.php HTTP/1.1
Host: example.com
Authorization: Basic alphanumerical ID
OAuth 2.0:
OAuth represents a step forward in the use of credentials for authentication of API service users. It is a major advance on the basic HTTP access authentication method. Today it is practically the only security method that is almost 100% reliable, and its reliability is based on creating unique authentication tokens for each user. If this access token is compromised, it is deleted and a new one is issued. This means that the API’s own credentials are safeguarded.
The authentication process is as follows:
A user launches a native application and is asked to give a username or email address and a password to identify themselves as a user.
The type of request used to send this credential to the API is a POST request, which ensures private delivery of secret data. This request is sent via the SSL (Secure Sockets Layer) protocol, designed to enable applications to transmit outbound data securely. SSL facilitates giving and receiving encryption keys between applications.
This request allows to validate user credentials and to create ad hoc an authentication or access token that will expire after a time, or if the user or developer responsible for the API believes it to have been breached.
This authentication token is stored in the device to facilitate access to the API’s services that support the application itself.
If we compare both methods, OAuth 2.0 provides better security criteria because any initial request for credentials is made under the SSL protocol and because the guaranteed access object is a temporary token. In the basic HTTP access authentication process, access to API services always relies on sending credentials via the web, specifically in the HTTP header, which makes it much vulnerable to third parties.
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).
I'm trying to wrap my head around 3-legged authentication to secure a restful API.
Currently I have a client application at app.host.com which needs to be accessed by multiple users with different account permissions and data, as well as the JSON RESTful api which holds all data at app_api.host.com
For 3-legged auth, I understand I first need a consumer key and secret belonging to the client app.host.com... I also understand an unauthorized request token must be provided by the service provider, which is given to the client, which is then redirected back to the service provider for authorization with a login dialog.
So does the login dialog then exist as a user interface on the API host at app_api.host.com? Doesn't this defeat the purpose of me building a purely JSON restful API separately to the client?
Or can I build the login dialog on the client which would then post the user/pwd details to another auth endpoint on the API and provide a 200 code when the request token is authorized? And then in turn the client would ask for permissions from the user which would again be posted to another endpoint which then responds with the appropriate access token for that user?
TL;DR: Am I able to have the login dialog exist on the client, which then posts data to the service provider? All guides I've read suggest having the dialog on the service provider, which in this case would defeat the purpose of having the api as a separate app altogether. How should I go about building this? Any available guides?
OAuth 2.0 defines different flows to use with different clients, depending on how much you trust the client.
Authorization code
The first and most secury flow is the authorization token flow. It is used with a traditional web application in which you can store secrets relatively securely (only people with admin privileges should have access to the client ID and secret stored in the configuration).
When the user (resource owner) wants to authenticate, the user-agent is redirected to the authorization server which belongs to the domain of the resource server (the data the client wants to consume, for example Facebook or Google). The authorization server presents the user with logon UI. When the user authenticates successfully, it presents the consent UI to ask if the user wants the client application to access the resource. If the user consents, the user-agent is redirected back to the client application with an authorization code. The client application can now use this code, its client ID and secret to talk to the authorization server directly and get an access token. In this flow, the access token is never in the hands of the user-agent.
Implicit flow
In the implicit flow, the user-agent (here typically a native (mobile) application or JavaScript client) redirects to the authorization server or opens a browser window to navigate to the authorization server. When the user authenticates successfully and grants permission to the client application, the access token itself is returned to the client. So the user-agent never sees the username and password the user enters (as this happens on a HTML page that is controlled by the resource server), but does have control over the access token.
Resource owner password credential flow
Here the user-agent is fully trusted and asks the user for username and password. It then communicates with the authorization server to get a access token. Even though the user-agent knows the credentials of the user, it only uses them once to get an access token. It does not need to send them along each request to the resource server.
So to answer your question, you can build the login dialog in your app if you think your users will trust your application enough to give you their credentials. Otherwise you should probably go for one of the other flows. You can read more on OAuth 2 here and here.