blob: c45cc373d02d31bd2991d1c4d02e0d9d59b4380a [file] [log] [blame]
margaretha641ea632022-05-17 10:27:59 +02001package de.ids_mannheim.korap.authentication;
2
Marc Kupietzd43a98d2023-09-22 17:11:46 +02003import static org.junit.jupiter.api.Assertions.assertEquals;
margaretha641ea632022-05-17 10:27:59 +02004
5import java.net.URI;
6import java.security.GeneralSecurityException;
margaretha641ea632022-05-17 10:27:59 +02007
8import org.apache.http.entity.ContentType;
Marc Kupietzd43a98d2023-09-22 17:11:46 +02009import org.junit.jupiter.api.AfterEach;
10import org.junit.jupiter.api.AfterAll;
11import org.junit.jupiter.api.BeforeEach;
12import org.junit.jupiter.api.BeforeAll;
13import org.junit.jupiter.api.Test;
margaretha641ea632022-05-17 10:27:59 +020014import org.springframework.beans.factory.annotation.Autowired;
15import org.springframework.util.MultiValueMap;
16import org.springframework.web.util.UriComponentsBuilder;
margaretha641ea632022-05-17 10:27:59 +020017import com.fasterxml.jackson.databind.JsonNode;
18import com.google.common.net.HttpHeaders;
margaretha641ea632022-05-17 10:27:59 +020019import com.unboundid.ldap.sdk.LDAPException;
margaretha641ea632022-05-17 10:27:59 +020020import de.ids_mannheim.korap.config.Attributes;
21import de.ids_mannheim.korap.config.FullConfiguration;
22import de.ids_mannheim.korap.constant.AuthenticationMethod;
23import de.ids_mannheim.korap.exceptions.KustvaktException;
24import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
25import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
26import de.ids_mannheim.korap.oauth2.dao.OAuth2ClientDao;
27import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
28import de.ids_mannheim.korap.oauth2.entity.AccessToken;
29import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
30import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
31import de.ids_mannheim.korap.utils.JsonUtils;
32import de.ids_mannheim.korap.web.controller.OAuth2TestBase;
33import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
margaretha96c309d2023-08-16 12:24:12 +020034import jakarta.ws.rs.client.Entity;
35import jakarta.ws.rs.core.Response;
36import jakarta.ws.rs.core.Response.Status;
margaretha641ea632022-05-17 10:27:59 +020037
38public class LdapOAuth2Test extends OAuth2TestBase {
39
40 @Autowired
41 private FullConfiguration config;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020042
margaretha641ea632022-05-17 10:27:59 +020043 @Autowired
44 private AccessTokenDao accessDao;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020045
margaretha641ea632022-05-17 10:27:59 +020046 @Autowired
47 private RefreshTokenDao refreshDao;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020048
margaretha641ea632022-05-17 10:27:59 +020049 @Autowired
50 private OAuth2ClientDao clientDao;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020051
margarethad5fb9492023-04-21 11:30:54 +020052 private String testUsername = "idsTestUser";
Marc Kupietzd43a98d2023-09-22 17:11:46 +020053
margaretha641ea632022-05-17 10:27:59 +020054 private String testUserEmail = "testuser@example.com";
Marc Kupietzd43a98d2023-09-22 17:11:46 +020055
margaretha641ea632022-05-17 10:27:59 +020056 private String redirectUri = "https://client.com/redirect";
57
Marc Kupietzd43a98d2023-09-22 17:11:46 +020058 @BeforeAll
margaretha35e1ca22023-11-16 22:00:01 +010059 static void startTestLDAPServer ()
60 throws LDAPException, GeneralSecurityException {
margaretha641ea632022-05-17 10:27:59 +020061 LdapAuth3Test.startDirectoryServer();
margaretha641ea632022-05-17 10:27:59 +020062 }
63
Marc Kupietzd43a98d2023-09-22 17:11:46 +020064 @AfterAll
margaretha35e1ca22023-11-16 22:00:01 +010065 static void stopTestLDAPServer () {
margaretha641ea632022-05-17 10:27:59 +020066 LdapAuth3Test.shutDownDirectoryServer();
67 }
68
Marc Kupietzd43a98d2023-09-22 17:11:46 +020069 @BeforeEach
margaretha35e1ca22023-11-16 22:00:01 +010070 public void setLDAPAuthentication () {
margaretha641ea632022-05-17 10:27:59 +020071 config.setOAuth2passwordAuthentication(AuthenticationMethod.LDAP);
72 }
73
Marc Kupietzd43a98d2023-09-22 17:11:46 +020074 @AfterEach
margaretha35e1ca22023-11-16 22:00:01 +010075 public void resetAuthenticationMethod () {
margaretha641ea632022-05-17 10:27:59 +020076 config.setOAuth2passwordAuthentication(AuthenticationMethod.TEST);
77 }
78
79 @Test
margaretha35e1ca22023-11-16 22:00:01 +010080 public void testRequestTokenPasswordUnknownUser ()
81 throws KustvaktException {
82 Response response = requestTokenWithPassword(superClientId,
83 clientSecret, "unknown", "password");
margaretha641ea632022-05-17 10:27:59 +020084 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +000085 String entity = response.readEntity(String.class);
margaretha641ea632022-05-17 10:27:59 +020086 JsonNode node = JsonUtils.readTree(entity);
margaretha641ea632022-05-17 10:27:59 +020087 assertEquals(2023, node.at("/errors/0/0").asInt());
margaretha35e1ca22023-11-16 22:00:01 +010088 assertEquals(node.at("/errors/0/1").asText(),
89 "LDAP Authentication failed due to unknown user or password!");
margaretha641ea632022-05-17 10:27:59 +020090 }
91
92 @Test
margaretha35e1ca22023-11-16 22:00:01 +010093 public void testMapEmailToUsername () throws KustvaktException {
94 Response response = requestTokenWithPassword(superClientId,
95 clientSecret, testUserEmail, "password");
abcpro173fe8f22022-11-08 19:56:52 +000096 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margaretha641ea632022-05-17 10:27:59 +020097 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha641ea632022-05-17 10:27:59 +020098 String accessToken = node.at("/access_token").asText();
99 AccessToken accessTokenObj = accessDao.retrieveAccessToken(accessToken);
margarethad5fb9492023-04-21 11:30:54 +0200100 assertEquals(testUsername, accessTokenObj.getUserId());
margaretha641ea632022-05-17 10:27:59 +0200101 String refreshToken = node.at("/refresh_token").asText();
102 RefreshToken rt = refreshDao.retrieveRefreshToken(refreshToken);
margarethad5fb9492023-04-21 11:30:54 +0200103 assertEquals(testUsername, rt.getUserId());
margaretha641ea632022-05-17 10:27:59 +0200104 testRegisterPublicClient(accessToken);
105 node = testRegisterConfidentialClient(accessToken);
106 String clientId = node.at("/client_id").asText();
107 String clientSecret = node.at("/client_secret").asText();
margaretha641ea632022-05-17 10:27:59 +0200108 testRequestTokenWithAuthorization(clientId, clientSecret, accessToken);
109 }
margaretha35e1ca22023-11-16 22:00:01 +0100110
margaretha641ea632022-05-17 10:27:59 +0200111 private void testRegisterPublicClient (String accessToken)
margaretha96c309d2023-08-16 12:24:12 +0200112 throws KustvaktException {
margaretha641ea632022-05-17 10:27:59 +0200113 OAuth2ClientJson json = new OAuth2ClientJson();
114 json.setName("LDAP test client");
115 json.setType(OAuth2ClientType.PUBLIC);
margaretha35e1ca22023-11-16 22:00:01 +0100116 json.setDescription(
117 "Test registering a public client with LDAP authentication");
118 Response response = target().path(API_VERSION).path("oauth2")
119 .path("client").path("register").request()
120 .header(Attributes.AUTHORIZATION, "Bearer " + accessToken)
121 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
122 .post(Entity.json(json));
abcpro173fe8f22022-11-08 19:56:52 +0000123 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margaretha641ea632022-05-17 10:27:59 +0200124 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha641ea632022-05-17 10:27:59 +0200125 String clientId = node.at("/client_id").asText();
126 OAuth2Client client = clientDao.retrieveClientById(clientId);
margarethad5fb9492023-04-21 11:30:54 +0200127 assertEquals(testUsername, client.getRegisteredBy());
margaretha641ea632022-05-17 10:27:59 +0200128 }
margaretha35e1ca22023-11-16 22:00:01 +0100129
margaretha641ea632022-05-17 10:27:59 +0200130 private JsonNode testRegisterConfidentialClient (String accessToken)
margaretha96c309d2023-08-16 12:24:12 +0200131 throws KustvaktException {
margaretha641ea632022-05-17 10:27:59 +0200132 OAuth2ClientJson json = new OAuth2ClientJson();
133 json.setName("LDAP test client");
134 json.setType(OAuth2ClientType.CONFIDENTIAL);
135 json.setRedirectURI(redirectUri);
margaretha35e1ca22023-11-16 22:00:01 +0100136 json.setDescription(
137 "Test registering a confidential client with LDAP authentication");
138 Response response = target().path(API_VERSION).path("oauth2")
139 .path("client").path("register").request()
140 .header(Attributes.AUTHORIZATION, "Bearer " + accessToken)
141 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
142 .post(Entity.json(json));
abcpro173fe8f22022-11-08 19:56:52 +0000143 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margaretha641ea632022-05-17 10:27:59 +0200144 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha641ea632022-05-17 10:27:59 +0200145 String clientId = node.at("/client_id").asText();
146 OAuth2Client client = clientDao.retrieveClientById(clientId);
margarethad5fb9492023-04-21 11:30:54 +0200147 assertEquals(testUsername, client.getRegisteredBy());
margaretha641ea632022-05-17 10:27:59 +0200148 return node;
149 }
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200150
margaretha35e1ca22023-11-16 22:00:01 +0100151 private void testRequestTokenWithAuthorization (String clientId,
152 String clientSecret, String accessToken) throws KustvaktException {
margaretha641ea632022-05-17 10:27:59 +0200153 String authHeader = "Bearer " + accessToken;
margaretha35e1ca22023-11-16 22:00:01 +0100154 Response response = target().path(API_VERSION).path("oauth2")
155 .path("authorize").queryParam("response_type", "code")
156 .queryParam("client_id", clientId)
157 .queryParam("client_secret", clientSecret)
158 .queryParam("scope", "search match_info").request()
159 .header(Attributes.AUTHORIZATION, authHeader).get();
160 assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
161 response.getStatus());
margaretha641ea632022-05-17 10:27:59 +0200162 URI redirectUri = response.getLocation();
margaretha35e1ca22023-11-16 22:00:01 +0100163 MultiValueMap<String, String> params = UriComponentsBuilder
164 .fromUri(redirectUri).build().getQueryParams();
margaretha641ea632022-05-17 10:27:59 +0200165 String code = params.getFirst("code");
margaretha35e1ca22023-11-16 22:00:01 +0100166 response = requestTokenWithAuthorizationCodeAndForm(clientId,
167 clientSecret, code);
abcpro173fe8f22022-11-08 19:56:52 +0000168 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margaretha641ea632022-05-17 10:27:59 +0200169 String at = node.at("/access_token").asText();
170 AccessToken accessTokenObj = accessDao.retrieveAccessToken(at);
margarethad5fb9492023-04-21 11:30:54 +0200171 assertEquals(testUsername, accessTokenObj.getUserId());
margaretha641ea632022-05-17 10:27:59 +0200172 String refreshToken = node.at("/refresh_token").asText();
173 RefreshToken rt = refreshDao.retrieveRefreshToken(refreshToken);
margarethad5fb9492023-04-21 11:30:54 +0200174 assertEquals(testUsername, rt.getUserId());
margaretha641ea632022-05-17 10:27:59 +0200175 }
176}