Is it safe to allow a third party client to create a valid JWT for our resource API? All the examples I've seen require we provide an authentication server for issuing the JWT to authorized clients.
I think you need understand the difference between resource server (RS) and authorization server (AS).
If you trust the third party client to do the token issuance and validation on your behalf, it is totally fine to delegate the token process to them.
With that said, the flow would be like this:
user-agent access your resource endpoint.
your security chain check if user has authenticated session, if yes, proceed the request.
if not, redirect user to third party authentication endpoint with token.
after successfully authenticate the user, callback to resume the resource access.
if failed, take the user to access denial page.
Related
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
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).
In OAuth 2 the client app exchanges an authorization code for an access token. And with the access token, the app can make API calls. However, I don't really get why OAuth 2 has this step; it seems like an extra step.
One reason I can think of is that the authorization code is given through a redirect call on the client side, so it has the potential to be compromised, thus it's short lived; whereas the access token is given server-to-server.
That is true, but there is also the secret API key that the app sends. Then why couldn't same be done with the authorization code?
Say there was no access token but just the authorization code. Then even if someone gets the authorization code, they wouldn't be able to do anything if the OAuth server also checked the secret key along with the authorization code.
It should allow the OAuth server to:
Make sure the request was made by the correct app (authenticate)
Determine what types of permission were granted (authorize)
Ability to get access_token directly (Implicit grant type) is required in the cases of JavaScript clients or web applications running in a browser. Because, these clients are not secure based on the options available for saving the client secret. The client id and secret are required to exchange authorization code for an access_token.
These two grant types exist to provide various levels of security when implementing authentication.
If the resource served by the API is extremely sensitive then you want at most security, which is provided by Authorization Code flow. In this grant type you validate the client (server side API or a mobile client) and the resource owner (user) before granting access to the resource. The access_token is not even exposed to the browser/ user (since a stolen token can give access to the resource), thus giving high degree of security. This flow is complex and involves more round trips to the authorization server, but, provides more security.
If you don't need that kind of security on a resource you can use Implicit grant type where the browser/ user has access to the token. This flow is simple with only one trip to authorization server. It will not validate the client. No need to save the client secret with the browser.
Hopefully this makes sense. Please let me know if you have any questions.
Thank you,
Soma.
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.
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.