Auth0 API + Spring: как проверить личность пользователя по успешному ответу API Auth0 - PullRequest
1 голос
/ 22 сентября 2019

Проблема

Я пытаюсь создать приложение, которое использует Auth0 SPA + React на веб-интерфейсе для аутентификации пользователей без необходимости иметь дело с паролями.Затем я хотел бы защитить любые конечные точки, которые я создаю, используя сервер Auth , который требуется создать с помощью Spring Framework .

Просто чтобы уточнить,поток будет

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 предоставляет, но у меня естьочень трудно понять, как заставить мою службу аутентификации проверить пользователя.

Я считаю, что пришел к выводу, что мне нужно создать " API"на Auth0 и захватите токен доступа и используйте его для проверки JWT, который в данном случае является просто токеном доступа , а не JWT, который мойфронтенд содержит.У меня также есть эта часть работы, но, кажется, нет способа узнать, кто пользователь.При тестировании этого API , после отправки действительного запроса мне возвращается

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

Хотя приятно знать, что я на правильном пути, кажется, я не могу понять,что делать с этим ответом, чтобы найти пользователя.

Ожидается

Я ожидаю, что смогу идентифицировать конкретного пользователя после проверки access_token из моего AuthСлужба

Код

У меня не так много кода, чтобы показать, но я предоставлю то, что я могу из моей службы Auth

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

ValidateController.java

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

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

}

1 Ответ

0 голосов
/ 22 сентября 2019

Прочитав документы, я нашел свое решение.

Оказывается, мне не нужно создавать " API " для Auth0 но вместо этого нужно использовать мои Приложения конечные точки из Auth0 . Auth0 предоставляет множество конечных точек на основе вашей учетной записи, которые вы можете использовать в любых своих приложениях (CLI, Server, Client и т. Д.), Если вы можете:

  • Сделайте HTTP-запрос
  • Укажите учетные данные

Таким образом, способ получения информации о пользователях объяснен здесь .

Поток данных

Используя мои проекты auth / stream data, это в значительной степени:

  • Используя @ auth0 / auth0-spa-js на внешнем интерфейсе, вы можете получить пользователей токен доступа после успешной аутентификации с использованием метода getTokenSilently () .

  • Отправка HTTP-запроса в Служба отдыха

  • Служба отдыха отправляет этот токен в вашу Службу аутентификации

  • Служба аутентификации отправляет GET запрос на https://myAuth0Username.auth0.com/userinfo с заголовком Authorization: Bearer ${access_token}. Пример

  • При успешной авторизации с Auth0

    • Возвращает информацию о ваших пользователях, такую ​​как "имя", "электронная почта "и т. д.
  • Иное

    • Возвращает 403 Запрещенный статус HTTP
  • Служба аутентификации , затем возвращает Пользовательский объект в Служба отдыха

  • Служба отдыха , затем выполняетнеобходимая логика для этой конечной точки (запрос БД, другой HTTP-запрос и т. д.)

Пример конечной точки службы аутентификации для проверки токенов и возврата пользователя

ValidateController.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(...) в качестве последнего аргумента

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