简体   繁体   中英

Authenticating Spring Boot APIs

Background:

I have some APIs routes (~15 or so) that I want to authenticate. Right now, I can run the spring boot server locally ( mvn spring boot run ) and call all of the APIs. I can also deploy to Heroku and call the APIs from the Heroku cloud platform. This is great!

Here are the problem:

  1. I need to provide authentication for the APIs. The idea is that when running the spring boot server, I would need to pass in a token in order for the API call to work. If not, then I should get some unauthorized error(401 or 403 I think). Additionally, I would need to be able to seperate these APIs by roles (user, admin, etc).

  2. Ideally, I would want to build a test client(perhaps a webpage) that could call these APIs. I'm not exactly sure how authentication would work here.

I'm a bit confused because I tried working with Auth0 but that only seems to apply for 1 API? Auth0 allows for me to generate tokens but I'm not exactly sure how to integrate it with SpringBoot. It asks for an audience but I'm not sure what that should(especially since I'm running the Spring Boot server locally).

The next thing I was going to look at was Spring Security.

Setup Sprint security for your application. There is even an example form Auth0 on hwoto do this: https://auth0.com/docs/quickstart/backend/java-spring-security5/interactive

Once you have spring security running you can annotate your methods accordingly. eg @PreAuthorize("isAuthenticated()")

If the authorization check fails spring will respond with the error code 403 automatically.

The audience of an access token is the resource-server the token was emitted for. In your case, probably http://localhost:8080 . This will change in production. This audience should be requested by clients when getting an access-token.

Resource-servers should be configured with spring-boot-starter-oauth2-resource-server . Spring default HTTP status for unauthorized request is 302 (redirect to login), but it is best practice for resource-servers to return 401, and it's an easy task:

http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
  response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Restricted Content\"");
  response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
});

For more details about resource-server configuration, you can have a look at this tutorials I wrote. It cover authorities mapping and role based access-control. It is designed for Keycloak, but switching to any other OIDC authorization-server (including Auth0) is mostly a matter of editing properties (except for the 1st tutorial where authorities converter implementation must be slightly modified to read the claim(s) you configured in Auth0 to put groups / roles).

How clients get an access token depends on the use-case: if acting on behalf of a user, authorization-code flow (with PKCE for "rich" clients) should be used, but we client is a acting in its own name (without the context of a specific authenticated user), then client-credentials should be used. For Spring clients (Thymeleaf UI as well as REST clients like WebClient , use spring-boot-starter-oauth2-client .

I strongly recommend you use JUnit instead of a client UI to test your app. Refer to the tutorials I already linked if you don't know how to mock identities and HTTP requests.

If you still want to build a client with UI to query your API, you might save quite some time by exposing OpenAPI spec (see springdoc-openapi for that) and generate a client library with openapi-generator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM