Рубрики
Без рубрики

Пружинная Защита С Auth0

Узнайте, как интегрировать Auth0 с Spring Security

Автор оригинала: Anshul Bansal.

1. Обзор

Auth0 предоставляет услуги аутентификации и авторизации для различных типов приложений, таких как Собственные, одностраничные приложения и веб-приложения|/. Кроме того, он позволяет реализовывать различные функции, такие как Единый вход, социальный вход и многофакторная аутентификация .

В этом руководстве мы рассмотрим безопасность Spring с помощью Auth0 с помощью пошагового руководства, а также ключевые конфигурации учетной записи Auth0.

2. Настройка Auth0

2.1. Регистрация Auth0

Во-первых, мы подпишемся на бесплатный план Auth0 , который обеспечивает доступ до 7 тысяч активных пользователей с неограниченным количеством логинов. Однако мы можем пропустить этот раздел, если он у нас уже есть:

2.2. Панель мониторинга

После входа в учетную запись Auth0 мы увидим панель мониторинга, которая выделяет такие детали, как действия при входе в систему, последние логины и новые регистрации:

2.3. Создайте новое приложение

Затем в меню Приложения мы создадим новое приложение OpenID Connect (OIDC) для весенней загрузки .

Кроме того, мы выберем Обычные веб-приложения как тип приложения из доступных опций, таких как Собственные , Одностраничные приложения и Приложения от машины к машине :

2.4. Настройки приложения

Далее мы настроим несколько URL-адресов приложений например URL-адреса обратного вызова и URL-адреса выхода из системы , указывающие на наше приложение:

2.5. Учетные данные Клиента

По крайней мере, мы получим значения Domain , Client ID, и Client Secret , связанные с нашим приложением:

Пожалуйста, держите эти учетные данные под рукой, потому что они необходимы для установки Auth0 в нашем приложении Spring Boot.

3. Настройка приложения Spring Boot

Теперь, когда ваша учетная запись Auth0 готова с ключевыми конфигурациями, мы готовы интегрировать безопасность Auth0 в приложение Spring Boot.

3.1. Maven

Во-первых, давайте добавим последнюю зависимость mvc-auth-commons Maven в ваш pom.xm l:


    com.auth0
    mvc-auth-commons
    1.2.0

3.2. Gradle

Аналогично, при использовании Gradle мы можем добавить зависимость mvc-auth-commons в файл build.gradle :

compile 'com.auth0:mvc-auth-commons:1.2.0'

3.3. применение.свойства

Наше приложение Spring Boot требует такой информации, как Идентификатор клиента и Секрет клиента для включения аутентификации учетной записи Auth0. Итак, мы добавим их в файл application.properties :

com.auth0.domain: dev-example.auth0.com
com.auth0.clientId: {clientId}
com.auth0.clientSecret: {clientSecret}

3.4. AuthConfig

Затем мы создадим класс AuthConfig для чтения свойств Auth0 из файла application.properties :

@Configuration
@EnableWebSecurity
public class AuthConfig extends WebSecurityConfigurerAdapter {
    @Value(value = "${com.auth0.domain}")
    private String domain;

    @Value(value = "${com.auth0.clientId}")
    private String clientId;

    @Value(value = "${com.auth0.clientSecret}")
    private String clientSecret;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http
          .authorizeRequests()
          .antMatchers("/callback", "/login", "/").permitAll()
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .loginPage("/login")
          .and()
          .logout().logoutSuccessHandler(logoutSuccessHandler()).permitAll();
    }
}

Кроме того, класс AuthConfig настроен на включение веб-безопасности путем расширения класса WebSecurityConfigurerAdapter .

3.5. Контроллер аутентификации

Наконец, мы добавим ссылку на компонент для класса Authentication Controller в уже обсужденный класс AuthConfig :

@Bean
public AuthenticationController authenticationController() throws UnsupportedEncodingException {
    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
    return AuthenticationController.newBuilder(domain, clientId, clientSecret)
      .withJwkProvider(jwkProvider)
      .build();
}

Здесь мы использовали класс JwkProviderBuilder при создании экземпляра класса AuthenticationController . Мы будем использовать это для извлечения открытого ключа для проверки подписи токена (по умолчанию токен подписывается с использованием алгоритма асимметричной подписи RS256).

Кроме того, контроллер аутентификации bean предоставляет URL-адрес авторизации для входа в систему и обрабатывает запрос обратного вызова.

4. AuthController

Затем мы создадим класс AuthController для функций входа в систему и обратного вызова:

@Controller
public class AuthController {
    @Autowired
    private AuthConfig config;

    @Autowired 
    private AuthenticationController authenticationController;
}

Здесь мы ввели зависимости классов AuthConfig и Authentication Controller , рассмотренных в предыдущем разделе.

4.1. Вход в систему

Давайте создадим метод login , который позволяет нашему приложению Spring Boot аутентифицировать пользователя:

@GetMapping(value = "/login")
protected void login(HttpServletRequest request, HttpServletResponse response) {
    String redirectUri = "http://localhost:8080/callback";
    String authorizeUrl = authenticationController.buildAuthorizeUrl(request, response, redirectUri)
      .withScope("openid email")
      .build();
    response.sendRedirect(authorizeUrl);
}

Метод buildAuthorizeUrl генерирует URL-адрес авторизации Auth0 и перенаправляет на экран входа Auth 0 по умолчанию.

4.2. Обратный вызов

Как только пользователь войдет в систему с учетными данными Auth0, запрос на обратный вызов будет отправлен в наше приложение Spring Boot. Для этого давайте создадим метод обратного вызова :

@GetMapping(value="/callback")
public void callback(HttpServletRequest request, HttpServletResponse response) {
    Tokens tokens = authenticationController.handle(request, response);
    
    DecodedJWT jwt = JWT.decode(tokens.getIdToken());
    TestingAuthenticationToken authToken2 = new TestingAuthenticationToken(jwt.getSubject(),
      jwt.getToken());
    authToken2.setAuthenticated(true);
    
    SecurityContextHolder.getContext().setAuthentication(authToken2);
    response.sendRedirect(config.getContextPath(request) + "/"); 
}

Мы обработали запрос обратного вызова, чтобы получить токен доступа и токен id , которые представляют успешную аутентификацию. Затем мы создали объект TestingAuthenticationToken , чтобы установить аутентификацию в SecurityContextHolder .

Тем не менее, мы можем создать нашу реализацию класса AbstractAuthenticationToken для лучшего удобства использования.

5. Домашний контролер

Наконец, мы создадим Домашний контроллер с отображением по умолчанию для нашей целевой страницы приложения:

@Controller
public class HomeController {
    @GetMapping(value = "/")
    @ResponseBody
    public String home(final Authentication authentication) {
        TestingAuthenticationToken token = (TestingAuthenticationToken) authentication;
        DecodedJWT jwt = JWT.decode(token.getCredentials().toString());
        String email = jwt.getClaims().get("email").asString();
        return "Welcome, " + email + "!";
    }
}

Здесь мы извлекли Декодированный объект JWT из токена id . Кроме того, информация о пользователе, такая как электронная почта, извлекается из утверждений.

Вот так! Наше приложение Spring Boot готово с поддержкой безопасности Auth0. Давайте запустим наше приложение с помощью команды Maven:

mvn spring-boot:run

При доступе к приложению по адресу localhost:8080/login , мы увидим страницу входа по умолчанию, предоставленную Auth0:

После входа в систему с использованием учетных данных зарегистрированного пользователя будет показано приветственное сообщение с электронной почтой пользователя:

Кроме того, мы найдем кнопку “Зарегистрироваться” (рядом с кнопкой “Войти”) на экране входа по умолчанию для самостоятельной регистрации.

6. Регистрация

6.1. Самостоятельная регистрация

Впервые мы можем создать учетную запись Auth0 с помощью кнопки “Зарегистрироваться”, а затем предоставить такую информацию, как адрес электронной почты и пароль:

6.2. Создать пользователя

Или мы можем создать нового пользователя из меню Users в учетной записи Auth0:

6.3. Настройки соединений

Кроме того, мы можем выбрать различные типы подключений, такие как база данных и социальный логин для регистрации/входа в наше приложение Spring Boot:

Кроме того, на выбор предоставляется широкий спектр социальных связей:

7. Контроллер выхода из системы

Теперь, когда мы увидели функции входа в систему и обратного вызова, мы можем добавить функцию выхода из системы в наше приложение Spring Boot .

Давайте создадим Контроллер выхода из системы класс, реализующий LogoutSuccessHandler класс:

@Controller
public class LogoutController implements LogoutSuccessHandler {
    @Autowired
    private AuthConfig config;

    @Override
    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse res, 
      Authentication authentication) {
        if (req.getSession() != null) {
            req.getSession().invalidate();
        }
        String returnTo = "http://localhost:8080/";
        String logoutUrl = "https://dev-example.auth0.com/v2/logout?client_id=" +
          config.getClientId() + "&returnTo=" +returnTo;
        res.sendRedirect(logoutUrl);
    }
}

Здесь метод onLogoutSuccess переопределяется для вызова URL-адреса выхода /v2/logout Auth0.

8. API управления Auth0

До сих пор мы видели интеграцию безопасности Auth0 в приложении Spring Boot. Теперь давайте взаимодействовать с API управления Auth0 (system API) в том же приложении.

8.1. Создайте новое приложение

Во-первых, чтобы получить доступ к API управления Auth0, мы создадим приложение Machine to Machine в учетной записи Auth0:

8.2. Авторизация

Затем мы добавим авторизацию в API управления Auth0 с разрешениями на чтение/создание пользователей:

8.3. Учетные данные Клиента

Наконец, мы получим Идентификатор клиента и Секрет клиента для доступа к приложению управления Auth0 из нашего приложения Spring Boot:

8.4. Токен доступа

Давайте сгенерируем маркер доступа для приложения управления Auth0, используя учетные данные клиента, полученные в предыдущем разделе:

public String getManagementApiToken() {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    JSONObject requestBody = new JSONObject();
    requestBody.put("client_id", "auth0ManagementAppClientId");
    requestBody.put("client_secret", "auth0ManagementAppClientSecret");
    requestBody.put("audience", "https://dev-example.auth0.com/api/v2/");
    requestBody.put("grant_type", "client_credentials"); 

    HttpEntity request = new HttpEntity(requestBody.toString(), headers);

    RestTemplate restTemplate = new RestTemplate();
    HashMap result = restTemplate
      .postForObject("https://dev-example.auth0.com/oauth/token", request, HashMap.class);

    return result.get("access_token");
}

Здесь мы сделали запрос REST на URL-адрес токена /oauth/token Auth 0, чтобы получить доступ и обновить токены.

Кроме того, мы можем сохранить эти учетные данные клиента в файле application.properties и прочитать его с помощью класса AuthConfig .

8.5. UserController

После этого давайте создадим класс UserController с помощью метода users :

@Controller
public class UserController {
    @GetMapping(value="/users")
    @ResponseBody
    public ResponseEntity users(HttpServletRequest request, HttpServletResponse response) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + getManagementApiToken());
        
        HttpEntity entity = new HttpEntity(headers);
        
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity result = restTemplate
          .exchange("https://dev-example.auth0.com/api/v2/users", HttpMethod.GET, entity, String.class);
        return result;
    }
}

Метод users извлекает список всех пользователей, выполнив запрос GET к API /api/v2/users Auth0 с помощью маркера доступа, сгенерированного в предыдущем разделе.

Итак, давайте обратимся к localhost:8080/users , чтобы получить ответ JSON, содержащий всех пользователей:

[{
    "created_at": "2020-05-05T14:38:18.955Z",
    "email": "[email protected]",
    "email_verified": true,
    "identities": [
        {
            "user_id": "5eb17a5a1cc1ac0c1487c37f78758",
            "provider": "auth0",
            "connection": "Username-Password-Authentication",
            "isSocial": false
        }
    ],
    "name": "[email protected]",
    "nickname": "ansh",
    "logins_count": 64
    // ...
}]

8.6. Создание пользователя

Аналогично, мы можем создать пользователя, отправив запрос POST в /api/v2/users Auth0 API:

@GetMapping(value = "/createUser")
@ResponseBody
public ResponseEntity createUser(HttpServletResponse response) {
    JSONObject request = new JSONObject();
    request.put("email", "[email protected]");
    request.put("given_name", "Norman");
    request.put("family_name", "Lewis");
    request.put("connection", "Username-Password-Authentication");
    request.put("password", "Pa33w0rd");
    
    // ...
    ResponseEntity result = restTemplate
      .postForEntity("https://dev-example.auth0.com/api/v2/users", request.toString(), String.class);
    return result;
}

Затем давайте обратимся к localhost:8080/create User и проверим данные нового пользователя:

{
    "created_at": "2020-05-10T12:30:15.343Z",
    "email": "[email protected]",
    "email_verified": false,
    "family_name": "Lewis",
    "given_name": "Norman",
    "identities": [
        {
            "connection": "Username-Password-Authentication",
            "user_id": "5eb7f3d76b69bc0c120a8901576",
            "provider": "auth0",
            "isSocial": false
        }
    ],
    "name": "[email protected]",
    "nickname": "norman.lewis",
    // ...
}

Аналогично, мы можем выполнять различные операции, такие как перечисление всех соединений, создание соединения, перечисление всех клиентов и создание клиента с помощью API Auth0, в зависимости от наших разрешений.

9. Заключение

В этом уроке мы изучили безопасность Spring с помощью Auth0.

Во-первых, мы настроили учетную запись Auth0 с необходимыми конфигурациями. Затем мы создали приложение Spring Boot и настроили application.properties для интеграции Spring Security с Auth0.

Затем мы рассмотрели возможность создания маркера API для API управления Auth0. Наконец, мы рассмотрели такие функции, как извлечение всех пользователей и создание пользователя.

Как обычно, все реализации кода доступны на GitHub .