Spring Gateway that generates JWT token - spring-security

I'm trying to build a Gateway with spring-cloud. It should do some logic if a JWT exists, and it doesn't exist, it should create it (from scratch). I've got some example from internet and all of them are using oauth2, and I don't want it.
Does anybody know from an example online similar what I'm talking about. I'm new with both spring-cloud-gateway and spring-security
I've tried the https://spring.io/blog/2019/08/16/securing-services-with-spring-cloud-gateway example, but I'm confused with all the oauth part.

To issue (create) an JWT, you must authenticate the user, the JWT is cryptographically signed (by the authenticator) proof that the request is sent from that user.
Separation of Concerns
Gateway
The concern of a Gateway is to route requests. And do that in a good way.
Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs
Authentication Service
The concern of an Authentication Service is to authenticate the users, e.g. be the only service that has access to the user password metadata and be the only service with access to private keys used to sign JWT tokens.
The separation of concern is the reason why these two components are designed as two different components. The gateway should not have access to the private key to sign JWT tokens, so it should instead redirect unauthenticated users to the Authentication Service (Single Sign On in your link).

Related

OAuth2 which flow to use for frontend to api to oauth communication/authentication

I am reading and reading, not sure why it's so hard to properly understand OAuth2 flows, which I thought I understand, until I wanted my own server.
So I have Frontend (web + mobile app aka resource owner), my own API server ( resource server )
and I want to create my own OAuth2 server.
So assuming, that on user registration, I am registering them on my OAuth2 server, saving username and hashed password ( I also want to save organization/project name, so I can user oauth2 server for multiple projects without worry of username duplicates)
Then Frontend obtains access+refresh tokens from OAuth2 server directly with password_grant. Or should I do it through my API and use CLIENT_ID/CLIENT_SERCRET with it (is that even an option)?
With access token, Frontend then now can communicate do my API(resource server)
API (resource server) then communicates with OAuth2 to validate access token - here I am not sure what's the common name of that action authorize or authenticate ?
Once access token is expired, Frontend (resource owner) can communicate directly to OAuth2 to obtain new access and refresh token. Or again - it should go through API and do it with CLIENT_ID/SECRET ?
Currently I did above implementation, but inside my API, but idea of OAuth2 is that it is separated server. Not sure how it will benefit me other than I will be able to use it for other project, but I guess with OAuth2 I can then expose API to public.
Question is, is above correct ? can someone help me wrap it with correct OAuth2 terminology ?
The frontend apps are not resource owners, but clients. Resource owners are users of these apps. These apps are so called public clients - they don't have a secure storage for their client secret, so they must not have a client secret. Instead, they should use PKCE (kind of one-time password) with the the auth code flow.
This way, they receive a refresh token they can use to get valid access tokens. The frontend apps use access tokens to authorize their requests to your backend. Your backend should validate them.
For more info, please see the current best practices - OAuth 2.0 for Browser-Based Apps and OAuth 2.0 for Native Apps.

Generate bearer tokens for social logged in users spring boot

I have a authorization server which generates and store bearer tokens for username and password log in using the oauth2 password grant. I want to integrate social sign in (Google and facebook) to my existing authorization server. Since my other resources are protected by authorization server how do I generate a Bearer tokens for google/facebook signed in users ? so i can access my protected resources using that token.
Note: Bearer tokens are stored in mysql db. (Using JdbcTokenStore)
Since I already have password grant implementation, I'am glad if you can give me direction to do with the current authorization service using spring-boot and spring security.
Thank you.
There are 2 main ways to implement this:
Federation, so that the Authorization Server manages integration with social identity providers
Handle different providers in your apps, which will add complexity to both your UIs and APIs
Personally I much prefer the first option, which only requires configuration changes - and no code changes in UIs and APIs. My Federated Logins Blog Post may help you to understand your architectural choices.
It is worth doing some early technical testing to see if these steps work:
Adding an OAuth web client to Google / Facebook
Adding an Identity Provider to your Authorization Server

OAuth2.0 and OpenID Connect Confusing

I am confused about the use of OAuth 2.0 as an Authorization method and OpenID Connect as an Authentication method.
Based on my knowledge OAuth 2.0 is only an Authorization method. In other words, this is the process to request an ACCESS_TOKEN and RECEIVE this ACCESS_TOKEN, like depicted in the image below in yellow ellipse: (simplified)
Before an OAuth 2.0 Client retrieves an ACCESS_TOKEN from an Authorization Server this Server should verify if the User allows it and this is an Authentication Process that OAuth 2.0 does not care about.
When OpenID Connect is included in the mix it allows for an Authentication Method as well, but in my knowledge OpenID Connect just adds a "Claim" in the JWT Token that holds information about user that is using the service, like: email, name and others.
My questions are:
Why not ignore OpenID Connect and just add more "claims" in OAuth
2.0 to get information about users?
Is my description of the flows correct?
OpenID Connect does not merely "add a claim in JWT Token" but:
it introduces a completely new token (id_token) with radically different
semantics than the OAuth 2.0 access_token and a standardized format that is understood by the Client as opposed to the access_token which is opaque to the Client
it "twists" the role of the Client, now becoming the "audience" (or: intended recipient) of a token (i.e. the id_token) whilst the audience of the access_token is still a remote entity (aka. Resource Server) and the Client is only the "presenter" of the latter
The 2nd item is the primary source of confusion between OAuth 2.0 and OpenID Connect.
I don't know if your method will work or not but you're totally free to roll your own authentication. After all, that's what Facebook, GitHub and many others did by customizing oauth2. There ended up being so many oauth2 "authentication" methods that it was never plug and play if you wanted to change your provider. I believe that's why OpenID connect was introduced--a common way of connecting and reasoning about authentication while building on the established oauth2 pattern for authorization. Use OpenID connect or don't...but if you don't you'll be reinventing the wheel.
#sdoxee answers explains thing correctly. But I am adding bit more information for OP's understanding.
These days many identity providers (eg:- Azure AD) issue JWT based access tokens. These JWT access tokens do contain claims about end user as well as JWT related validation details (eg:- Token expiration). Here is the link for Azure AD OAuth 2 success response which highlights access token to be a JWT. Also, see JWT claims to see how they explain the claims. Samples are given below,
family_name : User’s last name or surname. The application can display this value.
given_name : User’s first name. The application can display this value.
One could think of building authentication on claims present in access token, but this is not sticking with protocol. And mostly claims and user information will be implementer specific. Also, by protocol definition, these two tokens (id and access) have two different audiences.
ID token is for client, for validation and for authentication.
Access token is for OAuth 2 protected endpoint.
Again, as #sdoxee highlight, use the correct protocol at correct place. Having claims in access token does not necessarily mean you should use them for authentication.

Can I use Resource owner password flow with SPA?

I'm trying to implement authentication/authorization in my solution. I have a bunch of backend services(including identity service) under API Gateway, "backend for frontend" service, and SPA (React + Redux). I have read about OAuth2.0/OpenIdConnect, and I can't understand, why I shouldn't use Resource owner password flow?
A client ( my backend for frontend server ) is absolutely trusted, I can simply send users login/password to the server, then it forwards them to Identity server, receives the access token && refresh token and stores refresh token in memory(session, Redis, etc), and send the access token to SPA, which stores it in local storage. If SPA will send a request with the expired access token, the server will request a new one using refresh token and forwards the request to API Gateway with the new access token.
I think in my case a flows with redirects can provide worth user experience, and are too complicated.
What have I misunderstood? What potholes I'll hit if I'll implement authentication/authorization as I described above?
OAuth 2.0 specification's introduction section gives one key information on the problem it tries to solve. I have highlighted a section below,
In the traditional client-server authentication model, the client
requests an access-restricted resource (protected resource) on the
server by authenticating with the server using the resource owner's
credentials. In order to provide third-party applications access to
restricted resources, the resource owner shares its credentials with
the third party
As a summary what OAuth wants to provide is an authorization layer which removes the requirement of exposing end user credentials to a third party. To achieve this it presents several flows (ex:- Authorization code flow, Implicit flow etc.) to obtain tokens which are good enough to access protected resources.
But not all clients may able to adopt those flows. And this is the reason OAuth spec introduce ROPF. This is highlighted from following extraction,
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application.The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viable.
According to your explanation, you have a trust relationship with client. And your flow seems to be work fine. But from my end I see following issues.
Trust
The trust is between end user and the client application. When you release and use this as a product, will your end users trust your client and share their credentials.? For example, if your identity server is Azure AD, will end users share Azure credentials with your client.?
Trust may be not an issue if you are using a single identity server and it will be the only one you will ever use. Which brings us the next problem,
Support for multiple identity servers
One advantage you get with OAuth 2 and OpenID Connect is the ability to use multiple identity servers. For example, you may move between Azure AD, Identityserver or other identity servers which of customer's choice (ex:- they already use on internally and they want your app to use it). Now if your application wants to consume such identity servers, end users will have to share credentials with your client. Sometimes, these identity servers may not even support ROPF flow. And yet again TRUST become an issue.!
A solution ?
Well I see one good flow you can use. You have one front end server and a back-end server. I believe your client is the combination of both. If that's the case you could try to adopt authorization code flow. It's true your front end is a SPA. But you have a backend you can utilise to obtain tokens. Only challenge is to connect front end SPA with back end for token response (pass access token to SPA and store other tokens in back-end). With that approach, you avoid above mentioned issues.

OAuth 2.0 for REST Web services

i'm implementing a REST layer for an existing application. I have my userid and passwords stored in database and i would like to authenticate these credentials while calling my REST services. Note that this is a standalone application.
After investigation, I figured out 2 ways.
Basic implementation with HTTPS - this approach makes sure that
userid and password passed is not tampered by Man in middle attack.
Using Authentication Token(JWT) - user initially passes his userid
and password and server gives back an Authentication token.Once user
have an authentication token that could be used for subsequent
request.
Using OAuth 2.0 - I'm very confused in this approach. After reading the docs and specification, I found that since my application
is standalone, I need to implement Authorization Server, Resource
Server etc.
I'm asked to implement OAuth here, but i'm not convinced that OAuth is required in this scenario. I'm more inclined towards just implementing JWT(tokens)
Is OAuth really mandated in this scenario. What i understand about OAuth is it is used when you already have a service like Facebook/ Google.
Could someone pls confirm if my train of thoughts are correct and if OAuth 2.0 is required in this case?
The primary goal of OAuth 2.0 is to allow users to authenticate to use a client application via a third-party authentication provider (e.g. Google, Facebook, etc.), without exposing their credentials (typically a username/password) to the client.
In your case, if users are only ever going to authenticate to your system using their credentials in your database, then implementing OAuth 2.0 doesn't add any substantial value for you.
The OAuth 2.0 specification does define a "Resource Owner Password Credentials grant", intended for legacy use cases, that would apply to your situation: a user sends credentials, and you return an access token (that could be a JWT, if you like). If it's desirable from a management or marketing perspective, you could implement the Resource Owner Password Credentials grant and legitimately state that your application "conforms to a subset of OAuth2, as defined by RFC6749".

Resources