Автор оригинала: 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 ResponseEntitycreateUser(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 .