Fix login

This commit is contained in:
2025-12-04 16:11:56 +01:00
parent b280d5951f
commit 9f9c14c1bb
8 changed files with 412 additions and 1 deletions

View File

@@ -37,4 +37,28 @@ class TwitchEnvironmentValidationTest {
}
}
}
@Test
void stripsQuotesAndWhitespaceFromCredentials() {
ConfigurableApplicationContext context = null;
try {
context = new SpringApplicationBuilder(ImgfloatApplication.class)
.properties(
"server.port=0",
"TWITCH_CLIENT_ID=\" quoted-id \"",
"TWITCH_CLIENT_SECRET=' quoted-secret '"
)
.run();
var clientRegistrationRepository = context.getBean(org.springframework.security.oauth2.client.registration.ClientRegistrationRepository.class);
var twitch = clientRegistrationRepository.findByRegistrationId("twitch");
org.assertj.core.api.Assertions.assertThat(twitch.getClientId()).isEqualTo("quoted-id");
org.assertj.core.api.Assertions.assertThat(twitch.getClientSecret()).isEqualTo("quoted-secret");
} finally {
if (context != null) {
context.close();
}
}
}
}

View File

@@ -0,0 +1,57 @@
package com.imgfloat.app.config;
import org.junit.jupiter.api.Test;
import org.springframework.http.RequestEntity;
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.util.MultiValueMap;
import static org.assertj.core.api.Assertions.assertThat;
class TwitchAuthorizationCodeGrantRequestEntityConverterTest {
@Test
void addsClientIdAndSecretToTokenRequestBody() {
ClientRegistration registration = ClientRegistration.withRegistrationId("twitch")
.clientId("twitch-id")
.clientSecret("twitch-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("https://example.com/redirect")
.scope("user:read:email")
.authorizationUri("https://id.twitch.tv/oauth2/authorize")
.tokenUri("https://id.twitch.tv/oauth2/token")
.userInfoUri("https://api.twitch.tv/helix/users")
.userNameAttributeName("preferred_username")
.build();
OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
.authorizationUri(registration.getProviderDetails().getAuthorizationUri())
.clientId(registration.getClientId())
.redirectUri(registration.getRedirectUri())
.state("state")
.build();
OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.success("code")
.redirectUri(registration.getRedirectUri())
.state("state")
.build();
OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse);
OAuth2AuthorizationCodeGrantRequest grantRequest = new OAuth2AuthorizationCodeGrantRequest(registration, exchange);
var converter = new TwitchAuthorizationCodeGrantRequestEntityConverter();
RequestEntity<?> requestEntity = converter.convert(grantRequest);
MultiValueMap<String, String> body = (MultiValueMap<String, String>) requestEntity.getBody();
assertThat(body.getFirst(OAuth2ParameterNames.CLIENT_ID)).isEqualTo("twitch-id");
assertThat(body.getFirst(OAuth2ParameterNames.CLIENT_SECRET)).isEqualTo("twitch-secret");
}
}

View File

@@ -0,0 +1,76 @@
package com.imgfloat.app.config;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
import java.time.Instant;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
class TwitchOAuth2UserServiceTest {
@Test
void unwrapsTwitchUserAndAddsClientIdHeaderToUserInfoRequest() {
ClientRegistration registration = twitchRegistrationBuilder()
.clientId("client-123")
.clientSecret("secret")
.build();
OAuth2UserRequest userRequest = userRequest(registration);
RestTemplate restTemplate = TwitchOAuth2UserService.createRestTemplate(userRequest);
MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build();
TwitchOAuth2UserService service = new TwitchOAuth2UserService(ignored -> restTemplate);
server.expect(requestTo("https://api.twitch.tv/helix/users"))
.andExpect(method(HttpMethod.GET))
.andExpect(header("Client-ID", "client-123"))
.andRespond(withSuccess(
"{\"data\":[{\"id\":\"42\",\"login\":\"demo\",\"display_name\":\"Demo\"}]}",
MediaType.APPLICATION_JSON));
OAuth2User user = service.loadUser(userRequest);
assertThat(user.getName()).isEqualTo("demo");
assertThat(user.getAttributes())
.containsEntry("id", "42")
.containsEntry("display_name", "Demo");
server.verify();
}
private OAuth2UserRequest userRequest(ClientRegistration registration) {
OAuth2AccessToken accessToken = new OAuth2AccessToken(
OAuth2AccessToken.TokenType.BEARER,
"token",
Instant.now(),
Instant.now().plusSeconds(60),
Set.of("user:read:email"));
return new OAuth2UserRequest(registration, accessToken);
}
private ClientRegistration.Builder twitchRegistrationBuilder() {
return ClientRegistration.withRegistrationId("twitch")
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.clientName("Twitch")
.redirectUri("https://example.com/login/oauth2/code/twitch")
.authorizationUri("https://id.twitch.tv/oauth2/authorize")
.tokenUri("https://id.twitch.tv/oauth2/token")
.userInfoUri("https://api.twitch.tv/helix/users")
.userNameAttributeName("login");
}
}