1. Обзор
Auth0 предоставляет службы аутентификации и авторизации для различных типов приложений, таких как собственные приложения, одностраничные приложения и веб-приложения . Кроме того, он позволяет реализовать различные функции, такие как единый вход, вход через социальные сети и многофакторную аутентификацию .
В этом руководстве мы рассмотрим Spring Security с Auth0 с помощью пошагового руководства, а также ключевых конфигураций учетной записи Auth0.
2. Настройка Auth0
2.1. Auth0 Регистрация
Во- первых, мы подпишемся на бесплатный план Auth0 , который обеспечивает доступ до 7 тысяч активных пользователей с неограниченным количеством входов в систему. Однако мы можем пропустить этот раздел, если он у нас уже есть:
2.2. Приборная доска
После входа в учетную запись Auth0 мы увидим панель инструментов, на которой отображаются такие сведения, как действия при входе в систему, последние входы в систему и новые регистрации:
2.3. Создать новое приложение
Затем в меню «Приложения» мы создадим новое приложение OpenID Connect (OIDC) для Spring Boot .
Кроме того, мы выберем обычные веб-приложения
в качестве типа приложения
из доступных вариантов, таких как Native
, Single-Page Apps
и Machine to Machine Apps
:
2.4. Настройки приложения
Далее мы настроим несколько URI приложений
, таких как URL- адреса обратного вызова
и URL
-адреса выхода , указывающие на наше приложение:
2.5. Учетные данные клиента
Наконец, мы получим значения домена
, идентификатора
клиента и секрета клиента
, связанные с нашим приложением:
Держите эти учетные данные под рукой, потому что они необходимы для настройки Auth0 в нашем приложении Spring Boot.
3. Настройка приложения Spring Boot
Теперь, когда наша учетная запись Auth0 готова с ключевыми конфигурациями, мы готовы интегрировать безопасность Auth0 в приложение Spring Boot.
3.1. Мавен
Во-первых, давайте добавим последнюю зависимость mvc-auth-commons
Maven к нашему pom.xm
l:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>mvc-auth-commons</artifactId>
<version>1.2.0</version>
</dependency>
3.2. Грейдл
Точно так же при использовании 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
для чтения свойств 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. Контроллер аутентификации
Наконец, мы добавим ссылку на компонент для класса AuthenticationController
в уже обсуждаемый класс 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- компонент authenticationController
предоставляет URL-адрес авторизации для входа в систему и обрабатывает запрос обратного вызова.
4. Контроллер авторизации
Далее мы создадим класс AuthController
для функций входа и обратного вызова:
@Controller
public class AuthController {
@Autowired
private AuthConfig config;
@Autowired
private AuthenticationController authenticationController;
}
Здесь мы внедрили зависимости классов AuthConfig
и AuthenticationController
, которые обсуждались в предыдущем разделе.
4.1. Авторизоваться
Давайте создадим метод входа
в систему , который позволяет нашему приложению 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 и перенаправляет на экран входа Auth0 по умолчанию.
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) + "/");
}
Мы обработали запрос обратного вызова, чтобы получить accessToken
и idToken
, которые представляют собой успешную аутентификацию. Затем мы создали объект TestingAuthenticationToken
для установки аутентификации в SecurityContextHolder
.
Однако мы можем создать нашу реализацию класса AbstractAuthenticationToken
для большего удобства использования.
5. Домашний контроллер
Наконец, мы создадим HomeController
с сопоставлением по умолчанию для нашей целевой страницы приложения:
@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 + "!";
}
}
Здесь мы извлекли объект DecodedJWT
из idToken
. Кроме того, информация о пользователе, такая как электронная почта, извлекается из заявок.
Вот и все! Наше приложение Spring Boot готово с поддержкой безопасности Auth0. Давайте запустим наше приложение с помощью команды Maven:
mvn spring-boot:run
При доступе к приложению по адресу localhost:8080/login
мы увидим страницу входа по умолчанию, предоставленную Auth0 :
После входа в систему с использованием учетных данных зарегистрированного пользователя будет показано приветственное сообщение с адресом электронной почты пользователя:
Кроме того, мы найдем кнопку «Зарегистрироваться» (рядом с «Войти») на экране входа по умолчанию для самостоятельной регистрации.
6. Регистрация
6.1. Самостоятельная регистрация
Впервые мы можем создать учетную запись Auth0, нажав кнопку «Зарегистрироваться», а затем предоставив информацию, такую как адрес электронной почты и пароль:
6.2. Создать пользователя
Или мы можем создать нового пользователя из меню « Пользователи
» в учетной записи Auth0:
6.3. Настройки подключений
Кроме того, мы можем выбрать различные типы подключений, такие как база данных и вход через социальные сети для регистрации/входа в наше приложение Spring Boot:
Кроме того, на выбор доступен ряд социальных связей:
7. Логаутконтроллер
Теперь, когда мы увидели функции входа и обратного вызова, мы можем добавить функцию выхода из системы в наше приложение Spring Boot .
Создадим класс LogoutController , реализующий класс
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 (системный API) в том же приложении.
8.1. Создать новое приложение
Во-первых, чтобы получить доступ к API управления Auth0, мы создадим межмашинное приложение
в учетной записи Auth0:
8.2. Авторизация
Затем мы добавим авторизацию в Auth0 Management API с разрешениями на чтение/создание пользователей:
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<String> request = new HttpEntity<String>(requestBody.toString(), headers);
RestTemplate restTemplate = new RestTemplate();
HashMap<String, String> result = restTemplate
.postForObject("https://dev-example.auth0.com/oauth/token", request, HashMap.class);
return result.get("access_token");
}
Здесь мы сделали запрос REST к URL- адресу /oauth/token
Auth0 Token, чтобы получить токены доступа и обновления.
Кроме того, мы можем хранить эти учетные данные клиента в файле application.properties
и читать их с помощью класса AuthConfig
.
8.5. UserController
После этого создадим класс UserController
с методом users :
@Controller
public class UserController {
@GetMapping(value="/users")
@ResponseBody
public ResponseEntity<String> users(HttpServletRequest request, HttpServletResponse response) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + getManagementApiToken());
HttpEntity<String> entity = new HttpEntity<String>(headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> 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": "ansh@bans.com",
"email_verified": true,
"identities": [
{
"user_id": "5eb17a5a1cc1ac0c1487c37f78758",
"provider": "auth0",
"connection": "Username-Password-Authentication",
"isSocial": false
}
],
"name": "ansh@bans.com",
"nickname": "ansh",
"logins_count": 64
// ...
}]
8.6. Создать пользователя
Точно так же мы можем создать пользователя, отправив запрос POST к /api/v2/users
Auth0 API:
@GetMapping(value = "/createUser")
@ResponseBody
public ResponseEntity<String> createUser(HttpServletResponse response) {
JSONObject request = new JSONObject();
request.put("email", "norman.lewis@email.com");
request.put("given_name", "Norman");
request.put("family_name", "Lewis");
request.put("connection", "Username-Password-Authentication");
request.put("password", "Pa33w0rd");
// ...
ResponseEntity<String> result = restTemplate
.postForEntity("https://dev-example.auth0.com/api/v2/users", request.toString(), String.class);
return result;
}
Затем давайте получим доступ к localhost:8080/createUser
и проверим данные нового пользователя:
{
"created_at": "2020-05-10T12:30:15.343Z",
"email": "norman.lewis@email.com",
"email_verified": false,
"family_name": "Lewis",
"given_name": "Norman",
"identities": [
{
"connection": "Username-Password-Authentication",
"user_id": "5eb7f3d76b69bc0c120a8901576",
"provider": "auth0",
"isSocial": false
}
],
"name": "norman.lewis@email.com",
"nickname": "norman.lewis",
// ...
}
Similarly, we can perform various operations like listing all connections, creating a connection, listing all clients, and creating a client using Auth0 APIs, depending on our permissions.
9. Conclusion
In this tutorial, we explored Spring Security with Auth0.
First, we set up the Auth0 account with essential configurations. Then, we created a Spring Boot App and configured the application.properties
for Spring Security integration with Auth0.
Next, we looked into creating an API token for the Auth0 Management API. Last, we looked into features like fetching all users and creating a user.
As usual, all the code implementations are available over on GitHub .