简体   繁体   English

Auth0 API + Spring:如何从成功的 Auth0 API 响应中验证用户身份

[英]Auth0 API + Spring: How to verify user identity from successful Auth0 API response

Problem问题

I'm trying to create an app that uses Auth0 SPA + React on the frontend to auth users without ever having to deal with passwords.我正在尝试创建一个在前端使用Auth0 SPA + React的应用程序来验证用户,而无需处理密码。 Then, I'd like to secure any endpoints I create using an Auth server that I'm required to create using the Spring Framework .然后,我想保护我使用需要使用Spring Framework创建的Auth服务器创建的任何端点。

Just to clarify, the flow would be只是为了澄清,流程将是

Frontend ->
Auth through Auth0 ->
Redirect to users dashboard on frontend ->
Make HTTP request to endpoint sending JWT returned from Auth0 ->
Endpoint makes request to my Auth Server sending JWT returned from Auth0 ->
Auth server either either returns 401 or user object based on JWT ->
Endpoint grabs data specific to that user from DB ->
Returns data to frontend

I've managed to get my frontend to work just fine using the Quickstart Guide that Auth0 provides but I'm having a lot of trouble figuring out how to get my Auth Service to verify the user.我已经设法使用Auth0提供的快速入门指南让我的前端正常工作,但我在弄清楚如何让我的Auth 服务验证用户方面遇到了很多麻烦。

I believe I've come to the conclusion that I need to create an " API " on Auth0 and grab an access token and use that to validate the JWT, which in this case is just the access token and not the JWT that my frontend contains.我相信我已经得出结论,我需要在Auth0上创建一个“ API ”并获取一个访问令牌并使用它来验证 JWT,在这种情况下,它只是访问令牌,而不是包含我的前端的 Z1D1FADBD9140349C13578 . I've also got this part working but there doesn't seem to be a way to know who the user is.我也让这部分工作,但似乎没有办法知道用户是谁。 When testing this " API ", after sending a valid request I am returned在测试这个“ API ”时,发送有效请求后我被退回

{
  "iss": "https://${username}.auth0.com/",
  "sub": "${alphanumericCharacters}@clients",
  "aud": "${ApiIdentifier}",
  "iat": ${issuedAt},
  "exp": ${expiresAt},
  "azp": "${alphanumericCharacters}",
  "gty": "client-credentials"
}

While it's good to know I'm on the right track I can't seem to figure out what to do with this response to find the user.虽然很高兴知道我在正确的轨道上,但我似乎无法弄清楚如何处理此响应以找到用户。

Expected预期的

I expect to be able to identify a specific user after validating an access_token from my Auth Service我希望在验证来自我的身份验证服务access_token后能够识别特定用户

Code代码

I don't have much code to show but I'll provide what I can from my Auth Service我没有太多要显示的代码,但我会从我的身份验证服务中提供我所能提供的

SecurityConfiguration.java安全配置.java

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${auth0.audience}")
    private String audience;

    @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
    private String issuer;

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .mvcMatchers("/api/validate")
                    .authenticated()
                .and()
                .oauth2ResourceServer()
                    .jwt();
    }

    @Bean
    JwtDecoder jwtDecoder() {
        NimbusJwtDecoderJwkSupport jwtDecoder = (NimbusJwtDecoderJwkSupport)
                JwtDecoders.fromOidcIssuerLocation(issuer);

        OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(audience);
        OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
        OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);

        jwtDecoder.setJwtValidator(withAudience);

        return jwtDecoder;
    }

}

AudienceValidator.java AudienceValidator.java

public class AudienceValidator implements OAuth2TokenValidator<Jwt> {
    private final String audience;

    public AudienceValidator(String audience) {
        this.audience = audience;
    }

    public OAuth2TokenValidatorResult validate(Jwt jwt) {
        OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);

        if (jwt.getAudience().contains(audience)) {
            return OAuth2TokenValidatorResult.success();
        }
        return OAuth2TokenValidatorResult.failure(error);
    }
}

ValidateController.java验证控制器.java

@RestController
@RequestMapping("/api/validate")
public class ValidateController {

    @GetMapping
    public boolean validate() {
        return true;  // only returns if successfully authed
    }

}

After reading through the docs I've found my solution.通读文档后,我找到了解决方案。

It turns out that I don't need to create an " API " on Auth0 but instead need to use my Applications endspoint(s) from Auth0 .事实证明,我不需要在Auth0上创建“ API ”,而是需要使用来自Auth0Applications端点。 Auth0 provides many endpoints based on your account that you can take advantage of from any of your applications (CLI, Server, Client, etc.) as long as you can: Auth0根据您的帐户提供了许多端点,您可以从任何应用程序(CLI、服务器、客户端等)中利用这些端点,只要您可以:

  • Make an HTTP Request发出 HTTP 请求
  • Provide credentials提供凭据

So the way to get a users information is explained here .所以这里解释了获取用户信息的方法。

Data flow数据流

Using my projects auth/data flow it's pretty much:使用我的项目身份验证/数据流几乎是:

  • Using @auth0/auth0-spa-js on the frontend, you can grab a users access token after a successful auth by using the getTokenSilently() method .在前端使用@auth0/auth0-spa-js ,您可以通过使用getTokenSilently() 方法在成功验证后获取用户访问令牌

  • Send up HTTP request to your Rest Service向您的Rest 服务发送 HTTP 请求

  • Rest Service sends that token to your Auth Service Rest 服务将该令牌发送到您的身份验证服务

  • Auth Service sends GET request to https://myAuth0Username.auth0.com/userinfo with the Authorization: Bearer ${access_token} header. Auth Servicehttps://myAuth0Username.auth0.com/userinfo发送GET请求, Authorization: Bearer ${access_token} header。 Example例子

  • If successfully authed from Auth0如果从Auth0成功认证

    • Returns your users information such as "name", "email", etc.返回您的用户信息,例如“姓名”、“电子邮件”等。
  • Else别的

    • Returns a 403 Forbidden HTTP Status返回 403 禁止 HTTP 状态
  • Auth Service then returns user object to Rest Service Auth Service然后将用户 object返回到Rest 服务

  • Rest Service then does necessary logic for that endpoint (DB query, another HTTP request, etc.) Rest 服务然后为该端点执行必要的逻辑(数据库查询,另一个 HTTP 请求等)

Example Auth Service endpoint to validate tokens and return a user验证令牌并返回用户的示例身份验证服务端点

ValidateController.java验证控制器.java

package x.SpringTodo_Auth.Controllers;

import x.SpringTodo_Auth.Models.User;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/api/validate")
public class ValidateController {

    @GetMapping
    public Object validate() {
        // Create and set the "Authorization" header before sending HTTP request
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + access_token);
        HttpEntity<String> entity = new HttpEntity<>("headers", headers);

        // Use the "RestTemplate" API provided by Spring to make the HTTP request
        RestTemplate restTemplate = new RestTemplate();
        Object user = restTemplate.exchange("https://myAuth0Username.auth0.com/userinfo", HttpMethod.POST, entity, User.class);
        return user;
    }

}

User.java (This is the class passed to the restTemplate.exchange(...) method as the last argument User.java (这是作为最后一个参数传递给restTemplate.exchange(...)方法的 class

package x.SpringTodo_Auth.Models;

public class User {

    private String sub;
    private String given_name;
    private String family_name;
    private String nickname;
    private String name;
    private String picture;
    private String locale;
    private String updated_at;
    private String email;
    private boolean email_verified;

    // Getters/setters (or you can use Lombok)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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