Create a Secure Spring REST API

Michael Mogley

Great article. Please note that for Spring Webflux, the appropriate annotation appears to be @EnableReactiveMethodSecurity, NOT @EnableGlobalMethodSecurity. I was getting AuthenticationCredentialsNotFoundException: An Authentication object was not found in the Security Context, until I made this change (and also Mono-fied my controller method return value).

shantanu sardal

Nice article. However, I did not quite understand why we set the clientId, clientSecret and scopes in application.properties from the resource server application created in okta. I tried using random values for these 3 fields, and my endpoints work just fine. Why do we need to configure these?

Matt Raible

You might be using a newer version of Spring Boot than this tutorial calls for. Please check out latest one on how to Build a Secure Spring Data JPA Resource Server. If you have questions, comment on that post and I’ll be happy to help you there.

Santosh Singh

Hi, i am using same rest api through Postman, I got response message is 200 but i am not getting proper token.

Zhenying Gu

If the client of the rest API is not from the same organization, the client cannot be trusted, so the client credential grant type cannot be used, right? How does it work if the authorization code grant type is used to protect REST API? I think that the API client needs to get an authorization code and send it to the REST API for verification. How does the client get the authorization code? The client can get a session token from the authentication end point by providing username and password. Then the client can request an authorization code. However, the code is sent to the redirect_uri, which should be the RESP API URI. The client cannot get the authorization code. How does it work?

Brian Demers

I’m not sure I fully understand the question, but let me take a guess at what you are asking :slight_smile:

For an authorization code grant for a backend application (i.e. your spring backend) will redirect through your browser, and you will log in. When the flow returns to your backend, it will communicate with the IdP via the back channel. At that point your back channel has an access token, and will likely set a cookie for your browser. Any interaction with your Spring application at that point uses this cookie (no different from any web application). So if your REST endpoints live on the same server, it’s just cookies (and this is a good thing). If your backend needs to send that access token (on behalf of the user) to another service (some micro service), your micro service would be a “Resource Server” and would validate the token either as a JWT, or remotely (configured as “opaqueToken()” in Spring Security).

If you are NOT making a request on behalf of the user, then you would use the client credentials flow (maybe your web app is making a request to a weather service and that has nothing to do with the user). In this case your web-app could use an client-credentials flow to communicate with that 3rd party api to get an access token.
NOTE: that this token is separate from the user’s access token)

In my first example the token represents a user’s access. In the second it represents your web-app’s access.

So, it’s less about the “client cannot be trusted” and more about using the correct flow to obtain the access token. If you think about the pre-OAuth world you would probably do something similar. You would authenticate a user using one set of credentials (your user’s username/password), and you would make requests to the 3rd party using a different set of credentials.

I’m not sure I answered your question though (or if my response is a bit too ramble-y) let me know :slight_smile:

Oh, and check out this video, it’s long, but it covers one app using different token types for different things:
https://www.youtube.com/wat…

Zhenying Gu

Brian,

Thank you for your reply!

I want to protect a REST API, which will be used by external applications. The API provides multiple services. I’ll create multiple groups, each of them is allowed to access one service, and create a service account for each external application. When an external application logs in using the service account, the authentication/authorization system authenticate the account first and then determined if the account is allowed to access a particular service based on which group it is in. So there is no browser or human interaction during the authentication/authorization process. I would like to protect the REST API using okta. Since the applications that consume the services are external, the client credential flow cannot be used. I was thinking about using the authorization code flow to do that as the resource owner password flow is not recommended. When I think it again, I realize that the authorization code flow requires user involvement. If the application uses credential of the service account, that is the resource owner password flow anyway. I guess that I have to use the resource owner password flow in this scenario. Is that correct?