How do /oauth/authorize and /oauth/token interact in Spring OAuth? - spring

I am doing an in-depth study of Spring OAuth, and I found some conflicting information.
Specifically, this tutorial states that the /oauth/token endpoint handles the username and password before granting a refresh token to the client app. By contrast, the Spring OAuth Developer Guide mentions the /oauth/authorize and /oauth/token endpoints, but yet does not get specific about how they work.
Does the /oauth/authorize do 100% of the username/password/nOtherFactors check and then signal the /oauth/token endpoint to send a refresh token to the client, so that the client then sends the refresh token to the /oauth/token endpoint?
Or is all of it handled by the /oauth/token endpoint?
Is the relationship between /oauth/authorize and /oauth/token different for different grant types? How?

Per the OAuth 2.0 specification the authorize and token endpoints have different purposes.
Authorization endpoint is where the resource owner (user) logs in and grants authorization to the client (ex: web application running in the browser or an app running on a mobile device). This is typically used in scenarios where the resource owner's user agent (ex: browser) is redirected to the identity server (authorization server) for authentication. The resource owner's user agent will have direct access to the access token.
Token endpoint is where the client (ex: Server side API or mobile app) calls to exchange the Authorization Code, Client Id and Client Secret for an access token. In this scenario, the user agent is provided with an Authorization code only, no direct access to the access token. The client is a trusted party with access to client Id and Client secret from the authorization server (That is why I mentioned Server side API as the client).
Please read this article that has even better explanation.

Related

Spring boot API with both Oauth 2.0/OpenID Connect and internal authentication?

I'm having a hard time figuring a good way to implement Oauth 2.0 and OpenID Connect authentication alongside an existing internal email+password authentication for a B2B Web app's API using Spring security.
We have a backend REST API that is a Spring Boot servlet application which currently authenticates users with OAuth 1.0 and the password grant. The front-end is an Angular single-page app through which users must log in with their username and password. The API's /oauth/token endpoint then delivers an opaque access token to be used for fetching secured resources that are then displayed within the app.
We'd like to add the possibility to log in using external authentication with OpenID connect, which is a perfect opportunity for switching to OAuth 2.0 and JWT tokens. Our API would then accept JWT tokens it delivered as well as external JWT tokens emitted by accepted issuers.
Reading and validating JWT tokens won't be a problem using Spring security's OAuth Resource Server. However things get complicated with how to make the classic username+password login flow work with JWT tokens.
We thought about delivering JWT access tokens the same way we used to with our old OAuth 1.0 tokens. The thing is, newer OAuth specifications advise against using the password grant, plus it simply isn't supported in the Spring authorization server project we're planning to use. The authorization-code flow w/ PKCE seems like too much for this case as we do not want the back-end API to render a login form but use credentials entered in the existing login form that is part of the single-page app.
I've read a lot about not using OAuth for 1st party login since its primary use is for external authentication, but again, that doesn't apply since we also want 3rd party authentication.
What would be a secure way to implement a Spring boot authorization server that can deliver JWT access tokens to a 1st party client in exchange for a user's credentials, all this using the existing log in page, and given the password grant type no longer being supported?
I thought about implementing a preliminary step that would be a POST request with Basic authentication to a /login endpoint that just returns a 200 HTTP status, then proceeding to the /oauth2/authorize request that would deliver the authorization code immediately without redirecting since my session is authenticated.
I'll be happy to provide more details if needed. Here are the resources I'm using for this project.
What about setting up an authorization-server capable of identity federation?
In such configuration, the authorization-server is responsible for providing with identities, proxying one or more sources (your existing user database for instance, plus maybe Google, Facebook, Github, etc.)
Keycloak does it for instance.
From the client point of view (your Angular app), the authorization-server is used to get:
access-token: put in Authorization header of requests to secured resource-server(s) (can be a JWT or an opaque string, doesn't matter, clients should not try to extract data from access-tokens)
refresh-token: send to authorization-server to renew access-token before it expires
id-token: get user-profile data (email, username, profile picture, etc.)
You should have a look at https://github.com/damienbod/angular-auth-oidc-client for connecting an Angular app to an OIDC authorization-server.
From resource-server point of view, access-tokens are the source ofr setting-up security-context, either by decoding and validating a JWT locally or with token introspection on authorization-server.
Have a look at those tutorials for such resource-servers configuration.

Separating OAuth2 Authorization Server and Resource Server

I implementing OAuth2 Authorization Server and Resource Server.
and there are many documents told me
'Authorization Server and Resource Server can be Separated or not'
i like MSA, so i decided Separating these Servers.
i saw many documents in Internet about this issue, but i cant proceed anymore in practice.
i'm using SpringBoot2.
Scenario
User Connected to My Client Application.
Request to secured endpoint /client/me
in Client's Controller, if user has not authenticated, redirect to Authorization Server's login endpoint /auth/oauth/authorize.
if user comes in my Client App first, user will sign-up(not sign-in) in my Authorization Server.
in Authorization Server's sign-up page, user will input his username, realusername, password and email.
user's account has issued, and user will sign-in via my Authorization Server's login form.
if login succeed, Client will Request to Resource Server's /me endpoint with access-token, and Resource Server's Controller that mapped as /me will return Principal or Authentication Object as REST API.
Client will bind there REST API's results into DefaultOAuth2User
or CustomOAuth2User in my SecurityContext.
here is question.
As far as I know, Resource Server's /me endpoint will provide user's resources.
for example, realname or email etc.
but user has signed-up in Authorization Server, so all of information are saved in Authorization Server's Database.
my oauth2 servers are MSA. so DB has been separated too.
then, how can i setting email or realname to Principal or Authentication or CustomOAuth2User Object via Resource Server's /me endpoint?
Authorization Server is responsible for authenticating users or clients (other applications), checking if they are authorized to do what they want to do and on success, it issues a token. This means that a database it connects to should have all users credentials, clients IDs, clients secrets, roles, and other relevant information that helps in authentication and authorization.
Resource Server is responsible for handling all requests that came from frontend, be it authenticated requests or requests that are open (doesn't require authentication). Database it connects to should have information that is not relevant for authentication, like user's gender, height, weight, hobbies, etc.
To answer your question, you can create controllers in Resource Server that exposes registration, and other functionalities. This server will then make calls to Authorization Server. For registration, Resource Server will pass credentials to Auth Server to see if username is already claimed and if not register the user and based on the response of Auth Server, Resource Server will proceed with user registration. For login, frontend can make call to Auth Server directly to get token.
For all subsequent calls to protected resources (with access token) Resource Server would need to call Auth Server to verify tokens. For this Spring provides CheckTokenEndpoint (/oauth/check_token).
You can also check OAuth2RestTemplate. This can be used in Resource Server for making REST requests to Auth Server. Note that Resource Server (or any other internal application that you have like frontend) will be clients for Auth Server. They would also need to authenticate and authorize themselves.

Using our Own Oauth Authoriztion and Social Login Authorization in same server

We would like to have REST APIs with OAuth2 using our own user table for Authentication. Also, we need to allow Social Login. Below is the flow for social login,
Our OAuth
Client makes auth and access token URL for our servers to receive
the access token
Client sends access_token for further calls in the header as bearer
token
Social Login
Client makes auth and access token URL to Social Login server(For
ex,https://accounts.google.com/) to receive an access token
The client sends access_token for further calls in the header.
We have implemented our OAuth with Spring and working perfectly. We have questions on social login,
How to identify our own Oauth access token and social login access
token. We may have many social logins and we should able to identify corresponding social login.
How to validate and integrate with Spring Boot?
If the access tokens are just random strings, you probably cannot tell the issuer of the provided token and you cannot validate it.
I would suggest you to extend your OAuth2 server to accept third party providers (Google, Facebook ...) for authentication. This way would support both local and social users, but in your application, you would always deal with your own tokens. It would make the application security much easier (which usually means safer) and you could also configure your own scopes for access tokens. There are also ready to use solutions for it - e.g. Keycloak.

Which information gets sent in each API request using OIDC

I'm writing an API back-end that I want to use OpenID Connect (OIDC) to secure. I've been reading the documentation but I'm still a bit confused what process applies to each and every API request. The Open ID Connect code flow appears to be:
Which I'm fine with, as a one-time process. My back-end API sees an authorization code in the HTTP headers, and sends a request to the authorization server to get the id token. Assuming this validates OK, the data requested is returned in the API response.
But assuming the same user will then be making lots of requests to this API, what happens in subsequent requests? Is there some sort of session created in this mechanism? Do I continue to receive the same authorization code? Do I have to keep sending these back channel requests to the authorization server?
Or should I even output the JWT id token as a cookie? In this way I get the self contained id token coming back in future requests, with no need of a server side session, or further round trips.
I've been reading the documentation but I'm still a bit confused what
process applies to each and every API request
It is not the API that should follow OpenID connect protocol. It's the client that should do it.
My back-end API sees an authorization code in the HTTP headers, and
sends a request to the authorization server to get the id token.
Assuming this validates OK, the data requested is returned in the API
response.
Authorization code must be used by client application and not by the API endpoint. Also, authorization code must never be exposed to other entities.
You should use id token sent with OpenID Connect to authenticate the end user from your client application. To access API, you should use access tokens.
What to do in API endpoint ?
I think this is where you struggle. Your client application should send a valid access token to get access to API endpoint. From API endpoint, you can use OAuth 2.0 introspection endpoint to validate the tokens.
RFC7662 - OAuth 2.0 Token Introspection
This specification defines a protocol that allows authorized
protected resources to query the authorization server to determine
the set of metadata for a given token that was presented to them by
an OAuth 2.0 client.
Note that, OpenID Connect is built on top of OAuth 2.0. This means you can use anything defined in OAuth 2.0, including introspection endpoint. Use this endpoint to verify the access token validity.
What if you want end user details ?
OpenID Connect defines a user info endpoint
User info endpoint
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User. To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication. These Claims are normally represented by a JSON object that contains a collection of name and value pairs for the Claims.
Here also, you use access tokens to get user information from this endpoint. The response will let you know the end user to which this token was issued.
Depending on your specific API requirement, you can do a token introspection or obtain user information from user info endpoint. Once that is done you may go ahead and authenticate a session. You might use both endpoints if you need all available information.
Alternatively(instead of sessions) your API can maintain an access token cache. This will remove the need to validate tokens in each an every API call. But be aware that tokens have expiration time. You must consider about token expiration if you are choosing this solution.
p.s - Client vs Resource server
In OpenID Connect and OAuth 2.0 terms, a client could be a simple web page, desktop application or could be even server hosted application.
client
An application making protected resource requests on behalf of the
resource owner and with its authorization. The term "client" does
not imply any particular implementation characteristics (e.g.,
whether the application executes on a server, a desktop, or other
devices).
Obtaining tokens and using them is the duty of the client application.
On the other hand, resource server contains protected resources,
resource server
The server hosting the protected resources, capable of accepting
and responding to protected resource requests using access tokens.
Resource server exchange it's resources to access tokens. If we match the same scenario to basic authentication, access tokens replaces username/password sent with authentication headers.
Typically you'd secure a (pure) API with OAuth 2.0, not OpenID Connect. The Client accessing your API should obtain an OAuth 2.0 access token and in order to do that it may choose to use OpenID Connect to obtain that token. That is all independent of the API, which will only see the access token. The API (or Resource Server in OAuth 2.0 terminology) is not depicted in your diagram.

OneDrive App Access Token

Does anyone know how to get the app access token to a One-Drive API app?
I've tried combining {appId}|{appSecret} as the access_token param and as the Authorization header but it doesn't seem to work.
Thanks,
The OneDrive API docs have a good section on getting auth tokens with OAuth. In a nutshell, there are two services involved -- the OneDrive API service and the authentication service. The OneDrive API only accepts OAuth tokens that were issued by the authentication service. The authentication service is what you talk to first to get an auth token.
Depending on your app, you can either use the token flow or the code flow to get an auth token. In the 'token' flow, you navigate the user's browser to the authentication endpoint with your appId. The user may need to log in, consent, etc., and then the authentication endpoint redirects back to your site with an auth token you can use. The 'code' flow is similar to the 'token' flow, except it redirects back with an authentication code that your client app can use (along with its client secret) to obtain an auth token and a refresh token. Once you have a refresh token, you can use that to obtain future auth tokens without the user's involvement (as long as they granted the wl.offline_access scope).

Resources