簡體   English   中英

Auth0 API + Spring:如何從成功的 Auth0 API 響應中驗證用戶身份

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

問題

我正在嘗試創建一個在前端使用Auth0 SPA + React的應用程序來驗證用戶,而無需處理密碼。 然后,我想保護我使用需要使用Spring Framework創建的Auth服務器創建的任何端點。

只是為了澄清,流程將是

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

我已經設法使用Auth0提供的快速入門指南讓我的前端正常工作,但我在弄清楚如何讓我的Auth 服務驗證用戶方面遇到了很多麻煩。

我相信我已經得出結論,我需要在Auth0上創建一個“ API ”並獲取一個訪問令牌並使用它來驗證 JWT,在這種情況下,它只是訪問令牌,而不是包含我的前端的 Z1D1FADBD9140349C13578 . 我也讓這部分工作,但似乎沒有辦法知道用戶是誰。 在測試這個“ API ”時,發送有效請求后我被退回

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

雖然很高興知道我在正確的軌道上,但我似乎無法弄清楚如何處理此響應以找到用戶。

預期的

我希望在驗證來自我的身份驗證服務access_token后能夠識別特定用戶

代碼

我沒有太多要顯示的代碼,但我會從我的身份驗證服務中提供我所能提供的

安全配置.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

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);
    }
}

驗證控制器.java

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

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

}

通讀文檔后,我找到了解決方案。

事實證明,我不需要在Auth0上創建“ API ”,而是需要使用來自Auth0Applications端點。 Auth0根據您的帳戶提供了許多端點,您可以從任何應用程序(CLI、服務器、客戶端等)中利用這些端點,只要您可以:

  • 發出 HTTP 請求
  • 提供憑據

所以這里解釋了獲取用戶信息的方法。

數據流

使用我的項目身份驗證/數據流幾乎是:

  • 在前端使用@auth0/auth0-spa-js ,您可以通過使用getTokenSilently() 方法在成功驗證后獲取用戶訪問令牌

  • 向您的Rest 服務發送 HTTP 請求

  • Rest 服務將該令牌發送到您的身份驗證服務

  • Auth Servicehttps://myAuth0Username.auth0.com/userinfo發送GET請求, Authorization: Bearer ${access_token} header。 例子

  • 如果從Auth0成功認證

    • 返回您的用戶信息,例如“姓名”、“電子郵件”等。
  • 別的

    • 返回 403 禁止 HTTP 狀態
  • Auth Service然后將用戶 object返回到Rest 服務

  • Rest 服務然后為該端點執行必要的邏輯(數據庫查詢,另一個 HTTP 請求等)

驗證令牌並返回用戶的示例身份驗證服務端點

驗證控制器.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 (這是作為最后一個參數傳遞給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