fix(auth): preserve identity link provider failure codes

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-07-31 09:50:33 +08:00
parent 4874ce0dec
commit 740e049fba
3 changed files with 69 additions and 1 deletions

View file

@ -319,7 +319,8 @@ public class IdentityLinkAppService {
username,
password));
} catch (ProviderAuthenticationException exception) {
throw ProviderAuthenticationFailureMapper.map(exception);
throw ProviderAuthenticationFailureMapper
.mapIdentityLink(exception);
}
}

View file

@ -1,6 +1,8 @@
package com.iflytek.skillhub.service;
import com.iflytek.skillhub.auth.exception.AuthFlowException;
import com.iflytek.skillhub.auth.identity.IdentityLinkException;
import com.iflytek.skillhub.auth.identity.IdentityLinkFailureCode;
import com.iflytek.skillhub.auth.provider.ProviderAuthenticationException;
import org.springframework.http.HttpStatus;
@ -32,6 +34,24 @@ final class ProviderAuthenticationFailureMapper {
};
}
static IdentityLinkException mapIdentityLink(
ProviderAuthenticationException exception) {
IdentityLinkFailureCode reasonCode =
switch (exception.getReasonCode()) {
case UPSTREAM_INVALID_CREDENTIALS,
UPSTREAM_ACCESS_DENIED,
REPLAY_DETECTED ->
IdentityLinkFailureCode
.PROVIDER_AUTHENTICATION_FAILED;
case UPSTREAM_UNAVAILABLE,
UPSTREAM_MISCONFIGURED,
TLS_VALIDATION_FAILED,
UPSTREAM_INVALID_RESPONSE ->
IdentityLinkFailureCode.PROVIDER_UNAVAILABLE;
};
return new IdentityLinkException(reasonCode, exception);
}
private static AuthFlowException failure(
HttpStatus status,
String messageCode) {

View file

@ -3,6 +3,8 @@ package com.iflytek.skillhub.service;
import static org.assertj.core.api.Assertions.assertThat;
import com.iflytek.skillhub.auth.exception.AuthFlowException;
import com.iflytek.skillhub.auth.identity.IdentityLinkException;
import com.iflytek.skillhub.auth.identity.IdentityLinkFailureCode;
import com.iflytek.skillhub.auth.provider.ProviderAuthenticationException;
import com.iflytek.skillhub.auth.provider.ProviderAuthenticationFailureCode;
import org.junit.jupiter.api.Test;
@ -37,6 +39,33 @@ class ProviderAuthenticationFailureMapperTest {
HttpStatus.SERVICE_UNAVAILABLE);
}
@Test
void mapsStableProviderFailuresToIdentityLinkReasonCodes() {
assertIdentityLinkMapping(
ProviderAuthenticationFailureCode
.UPSTREAM_INVALID_CREDENTIALS,
IdentityLinkFailureCode.PROVIDER_AUTHENTICATION_FAILED);
assertIdentityLinkMapping(
ProviderAuthenticationFailureCode.UPSTREAM_ACCESS_DENIED,
IdentityLinkFailureCode.PROVIDER_AUTHENTICATION_FAILED);
assertIdentityLinkMapping(
ProviderAuthenticationFailureCode.REPLAY_DETECTED,
IdentityLinkFailureCode.PROVIDER_AUTHENTICATION_FAILED);
assertIdentityLinkMapping(
ProviderAuthenticationFailureCode.UPSTREAM_UNAVAILABLE,
IdentityLinkFailureCode.PROVIDER_UNAVAILABLE);
assertIdentityLinkMapping(
ProviderAuthenticationFailureCode.UPSTREAM_MISCONFIGURED,
IdentityLinkFailureCode.PROVIDER_UNAVAILABLE);
assertIdentityLinkMapping(
ProviderAuthenticationFailureCode.TLS_VALIDATION_FAILED,
IdentityLinkFailureCode.PROVIDER_UNAVAILABLE);
assertIdentityLinkMapping(
ProviderAuthenticationFailureCode
.UPSTREAM_INVALID_RESPONSE,
IdentityLinkFailureCode.PROVIDER_UNAVAILABLE);
}
private void assertMapping(
ProviderAuthenticationFailureCode reasonCode,
HttpStatus status) {
@ -51,4 +80,22 @@ class ProviderAuthenticationFailureMapperTest {
assertThat(mapped.getMessage())
.doesNotContain("private upstream detail");
}
private void assertIdentityLinkMapping(
ProviderAuthenticationFailureCode providerReasonCode,
IdentityLinkFailureCode identityLinkReasonCode) {
IdentityLinkException mapped =
ProviderAuthenticationFailureMapper.mapIdentityLink(
new ProviderAuthenticationException(
providerReasonCode,
new IllegalStateException(
"private upstream detail")));
assertThat(mapped.getStatus())
.isEqualTo(identityLinkReasonCode.status());
assertThat(mapped.getReasonCode())
.isEqualTo(identityLinkReasonCode);
assertThat(mapped.getMessage())
.doesNotContain("private upstream detail");
}
}