BAEL 6160 (#13519)
* [BAEL-4849] Article code * [BAEL-4968] Article code * [BAEL-4968] Article code * [BAEL-4968] Article code * [BAEL-4968] Remove extra comments * [BAEL-5258] Article Code * [BAEL-2765] PKCE Support for Secret Clients * [BAEL-5698] Article code * [BAEL-5698] Article code * [BAEL-5900] Initial commit * [BAEL-5974] Article Code * [BAEL-5974] Article Code * [BAEL-6160] Article code * [BAEL-6160] Tests --------- Co-authored-by: Philippe Sevestre <psevestre@gmail.com>
This commit is contained in:
parent
8fd4ad46ea
commit
a713d96d4d
@ -21,7 +21,7 @@ public class SentryFilter implements Filter {
|
|||||||
try {
|
try {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
int rc = ((HttpServletResponse) response).getStatus();
|
int rc = ((HttpServletResponse) response).getStatus();
|
||||||
if (rc/100 == 5) {
|
if (rc / 100 == 5) {
|
||||||
Sentry.captureMessage("Application error: code=" + rc, SentryLevel.ERROR);
|
Sentry.captureMessage("Application error: code=" + rc, SentryLevel.ERROR);
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# Sentry configuration file
|
# Sentry configuration file
|
||||||
# put your DSN here
|
# put your own DSN here. This one is NOT valid !!!
|
||||||
dsn=https://xxxxxxxxxxxxxxxx@zzzzzzz.ingest.sentry.io/wwww
|
dsn=https://c295098aadd04f719f1c9f50d801f93e@o75061.ingest.sentry.io/4504455033978880
|
@ -49,6 +49,7 @@
|
|||||||
<module>spring-security-web-x509</module>
|
<module>spring-security-web-x509</module>
|
||||||
<module>spring-security-opa</module>
|
<module>spring-security-opa</module>
|
||||||
<module>spring-security-pkce</module>
|
<module>spring-security-pkce</module>
|
||||||
|
<module>spring-security-azuread</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
76
spring-security-modules/spring-security-azuread/pom.xml
Normal file
76
spring-security-modules/spring-security-azuread/pom.xml
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>spring-security-azuread</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-oauth2-client</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.baeldung.security.azuread;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.baeldung.security.azuread.config;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
|
||||||
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
|
||||||
|
import org.springframework.security.oauth2.client.registration.ClientRegistration.ProviderDetails;
|
||||||
|
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
import com.baeldung.security.azuread.support.GroupsClaimMapper;
|
||||||
|
import com.baeldung.security.azuread.support.NamedOidcUser;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties(JwtAuthorizationProperties.class)
|
||||||
|
public class JwtAuthorizationConfiguration {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain customJwtSecurityChain(HttpSecurity http, JwtAuthorizationProperties props) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
return http
|
||||||
|
.authorizeRequests( r -> r.anyRequest().authenticated())
|
||||||
|
.oauth2Login(oauth2 -> {
|
||||||
|
oauth2.userInfoEndpoint(ep ->
|
||||||
|
ep.oidcUserService(customOidcUserService(props)));
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
private OAuth2UserService<OidcUserRequest, OidcUser> customOidcUserService(JwtAuthorizationProperties props) {
|
||||||
|
final OidcUserService delegate = new OidcUserService();
|
||||||
|
final GroupsClaimMapper mapper = new GroupsClaimMapper(
|
||||||
|
props.getAuthoritiesPrefix(),
|
||||||
|
props.getGroupsClaim(),
|
||||||
|
props.getGroupToAuthorities());
|
||||||
|
|
||||||
|
return (userRequest) -> {
|
||||||
|
OidcUser oidcUser = delegate.loadUser(userRequest);
|
||||||
|
// Enrich standard authorities with groups
|
||||||
|
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
|
||||||
|
mappedAuthorities.addAll(oidcUser.getAuthorities());
|
||||||
|
mappedAuthorities.addAll(mapper.mapAuthorities(oidcUser));
|
||||||
|
|
||||||
|
oidcUser = new NamedOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo(),oidcUser.getName());
|
||||||
|
|
||||||
|
return oidcUser;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// @Bean
|
||||||
|
// GrantedAuthoritiesMapper jwtAuthoritiesMapper(JwtAuthorizationProperties props) {
|
||||||
|
// return new MappingJwtGrantedAuthoritiesMapper(
|
||||||
|
// props.getAuthoritiesPrefix(),
|
||||||
|
// props.getGroupsClaim(),
|
||||||
|
// props.getGroupToAuthorities());
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.baeldung.security.azuread.config;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Baeldung
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties(prefix="baeldung.jwt.authorization")
|
||||||
|
public class JwtAuthorizationProperties {
|
||||||
|
|
||||||
|
// Claim that has the group list
|
||||||
|
private String groupsClaim = "groups";
|
||||||
|
|
||||||
|
private String authoritiesPrefix = "ROLE_";
|
||||||
|
|
||||||
|
// map groupIds to a list of authorities.
|
||||||
|
private Map<String,List<String>> groupToAuthorities = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the groupsClaim
|
||||||
|
*/
|
||||||
|
public String getGroupsClaim() {
|
||||||
|
return groupsClaim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param groupsClaim the groupsClaim to set
|
||||||
|
*/
|
||||||
|
public void setGroupsClaim(String groupsClaim) {
|
||||||
|
this.groupsClaim = groupsClaim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the groupToAuthorities
|
||||||
|
*/
|
||||||
|
public Map<String, List<String>> getGroupToAuthorities() {
|
||||||
|
return groupToAuthorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param groupToAuthorities the groupToAuthorities to set
|
||||||
|
*/
|
||||||
|
public void setGroupToAuthorities(Map<String, List<String>> groupToAuthorities) {
|
||||||
|
this.groupToAuthorities = groupToAuthorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the authoritiesPrefix
|
||||||
|
*/
|
||||||
|
public String getAuthoritiesPrefix() {
|
||||||
|
return authoritiesPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param authoritiesPrefix the authoritiesPrefix to set
|
||||||
|
*/
|
||||||
|
public void setAuthoritiesPrefix(String authoritiesPrefix) {
|
||||||
|
this.authoritiesPrefix = authoritiesPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.baeldung.security.azuread.controllers;
|
||||||
|
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/")
|
||||||
|
@Slf4j
|
||||||
|
public class IndexController {
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String index(Model model, Authentication user) {
|
||||||
|
log.info("GET /: user={}", user);
|
||||||
|
model.addAttribute("user", user);
|
||||||
|
return "index";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.baeldung.security.azuread.support;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||||
|
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||||
|
import org.springframework.security.oauth2.jwt.Jwt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Baeldung
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GroupsClaimMapper {
|
||||||
|
|
||||||
|
private final String authoritiesPrefix;
|
||||||
|
private final String groupsClaim;
|
||||||
|
private final Map<String, List<String>> groupToAuthorities;
|
||||||
|
|
||||||
|
public GroupsClaimMapper(String authoritiesPrefix, String groupsClaim, Map<String, List<String>> groupToAuthorities) {
|
||||||
|
this.authoritiesPrefix = authoritiesPrefix;
|
||||||
|
this.groupsClaim = groupsClaim;
|
||||||
|
this.groupToAuthorities = Collections.unmodifiableMap(groupToAuthorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<? extends GrantedAuthority> mapAuthorities(ClaimAccessor source) {
|
||||||
|
|
||||||
|
List<String> groups = source.getClaimAsStringList(groupsClaim);
|
||||||
|
if ( groups == null || groups.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GrantedAuthority> result = new ArrayList<>();
|
||||||
|
for( String g : groups) {
|
||||||
|
List<String> authNames = groupToAuthorities.get(g);
|
||||||
|
if ( authNames == null ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SimpleGrantedAuthority> mapped = authNames.stream()
|
||||||
|
.map( s -> authoritiesPrefix + s)
|
||||||
|
.map( SimpleGrantedAuthority::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
result.addAll(mapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.baeldung.security.azuread.support;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||||
|
|
||||||
|
public class NamedOidcUser extends DefaultOidcUser {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final String userName;
|
||||||
|
|
||||||
|
public NamedOidcUser(Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken,
|
||||||
|
OidcUserInfo userInfo, String userName) {
|
||||||
|
super(authorities,idToken,userInfo);
|
||||||
|
this.userName= userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.userName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
spring:
|
||||||
|
security:
|
||||||
|
oauth2:
|
||||||
|
client:
|
||||||
|
provider:
|
||||||
|
azure:
|
||||||
|
issuer-uri: https://login.microsoftonline.com/2e9fde3a-38ec-44f9-8bcd-c184dc1e8033/v2.0
|
||||||
|
user-name-attribute: name
|
||||||
|
registration:
|
||||||
|
azure-dev:
|
||||||
|
provider: azure
|
||||||
|
#client-id: "6035bfd4-22f0-437c-b76f-da729a916cbf"
|
||||||
|
#client-secret: "fo28Q~-aLbmQvonnZtzbgtSiqYstmBWEmGPAodmx"
|
||||||
|
client-id: your-client-id
|
||||||
|
client-secret: your-secret-id
|
||||||
|
scope:
|
||||||
|
- openid
|
||||||
|
- email
|
||||||
|
- profile
|
||||||
|
|
||||||
|
# Group mapping
|
||||||
|
baeldung:
|
||||||
|
jwt:
|
||||||
|
authorization:
|
||||||
|
group-to-authorities:
|
||||||
|
"ceef656a-fca9-49b6-821b-f7543b7065cb": BAELDUNG_RW
|
||||||
|
"eaaecb69-ccbc-4143-b111-7dd1ce1d99f1": BAELDUNG_RO,BAELDUNG_ADMIN
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-theme="dark" >
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Insert title here</title>
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
|
||||||
|
</head>
|
||||||
|
<body class="container">
|
||||||
|
<h1>Hello, <span data-th-text="${user.name}">NOMO_NOMO</span></h1>
|
||||||
|
|
||||||
|
<h2>User info:</h2>
|
||||||
|
|
||||||
|
<table role="grid">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Attribute</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Name</td>
|
||||||
|
<td data-th-text="${user.name}">user.name</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Class</td>
|
||||||
|
<td data-th-text="${user.class}">user.class</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Principal Class</td>
|
||||||
|
<td data-th-text="${user.principal.class}">user.principal.class</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>isAuthenticated?</td>
|
||||||
|
<td data-th-text="${user.authenticated}">user.authenticated</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>clientRegistrationId</td>
|
||||||
|
<td data-th-text="${user.authorizedClientRegistrationId}">user.authorizedClientregistrationId</td>
|
||||||
|
</tr>
|
||||||
|
<tr data-th-each="claim : ${user.principal.claims}">
|
||||||
|
<td >Claim: <span data-th-text="${claim.key}">key</span></td>
|
||||||
|
<td data-th-text="${claim.value}">value</td>
|
||||||
|
</tr>
|
||||||
|
<tr data-th-each="ga : ${user.authorities}">
|
||||||
|
<td >Granted Authority: <span data-th-text="${ga.class.simpleName}"></span></td>
|
||||||
|
<td data-th-text="${ga.authority}">authority</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.baeldung.security.azuread;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||||
|
@ActiveProfiles("azuread")
|
||||||
|
class ApplicationLiveTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TestRestTemplate rest;
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
int port;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testWhenAccessRootPath_thenRedirectToAzureAD() {
|
||||||
|
|
||||||
|
ResponseEntity<String> response = rest.getForEntity("http://localhost:" + port , String.class);
|
||||||
|
HttpStatus st = response.getStatusCode();
|
||||||
|
assertThat(st)
|
||||||
|
.isEqualTo(HttpStatus.FOUND);
|
||||||
|
|
||||||
|
URI location1 = response.getHeaders().getLocation();
|
||||||
|
assertThat(location1)
|
||||||
|
.isNotNull();
|
||||||
|
assertThat(location1.getPath())
|
||||||
|
.isEqualTo("/oauth2/authorization/azure-dev");
|
||||||
|
|
||||||
|
assertThat(location1.getPort())
|
||||||
|
.isEqualTo(port);
|
||||||
|
|
||||||
|
assertThat(location1.getHost())
|
||||||
|
.isEqualTo("localhost");
|
||||||
|
|
||||||
|
// Now let't follow this redirect
|
||||||
|
response = rest.getForEntity(location1, String.class);
|
||||||
|
assertThat(st)
|
||||||
|
.isEqualTo(HttpStatus.FOUND);
|
||||||
|
URI location2 = response.getHeaders().getLocation();
|
||||||
|
assertThat(location2)
|
||||||
|
.isNotNull();
|
||||||
|
|
||||||
|
assertThat(location2.getHost())
|
||||||
|
.describedAs("Should redirect to AzureAD")
|
||||||
|
.isEqualTo("login.microsoftonline.com");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.baeldung.security.azuread.support;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||||
|
|
||||||
|
class GroupsClaimMapperUnitTest {
|
||||||
|
|
||||||
|
private Map<String,List<String>> g2a = new HashMap<>();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testWhenNoGroupClaimsPresent_thenNoAuthoritiesAdded() {
|
||||||
|
|
||||||
|
ClaimAccessor source = mock(ClaimAccessor.class);
|
||||||
|
GroupsClaimMapper mapper = new GroupsClaimMapper("ROLE", "group", g2a);
|
||||||
|
|
||||||
|
Collection<? extends GrantedAuthority> authorities = mapper.mapAuthorities(source);
|
||||||
|
assertThat(authorities)
|
||||||
|
.isNotNull()
|
||||||
|
.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testWhenEmptyGroupClaimsPresent_thenNoAuthoritiesAdded() {
|
||||||
|
|
||||||
|
ClaimAccessor source = mock(ClaimAccessor.class);
|
||||||
|
when(source.getClaimAsStringList("group"))
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
GroupsClaimMapper mapper = new GroupsClaimMapper("ROLE", "group", g2a);
|
||||||
|
|
||||||
|
Collection<? extends GrantedAuthority> authorities = mapper.mapAuthorities(source);
|
||||||
|
assertThat(authorities)
|
||||||
|
.isNotNull()
|
||||||
|
.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user