Why are the redirect URIs configured to 127.0.0.1 instead of localhost?

120 Views Asked by At

I was following this Demo example and was wondering why the Auth server config reads

          redirect-uris:
            - "http://127.0.0.1:1234/login/oauth2/code/my-webapp-client-oidc"
            - "http://127.0.0.1:1234/authorized"
          post-logout-redirect-uris:
            - "http://127.0.0.1:1234/logged-out"

instead of

          redirect-uris:
            - "http://localhost:1234/login/oauth2/code/my-webapp-client-oidc"
            - "http://localhost:1234/authorized"
          post-logout-redirect-uris:
            - "http://localhost:1234/logged-out"

I would assume that it makes no difference but it does. When changing the URIs to localhost, the auth server gives me an exception when trying to login:

org.springframework.security.access.AccessDeniedException: Access Denied
    at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:98) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) ~[spring-security-web-6.2.1.jar:6.2.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.2.1.jar:6.2.1]
    at...

Could you please explain that to me? Thank you.

2

There are 2 best solutions below

0
J Asgarov On

it shouldn't matter whether u use localhost or 127.0.0.1 or if you buy a domain name and attach it to your computer and use that. What DOES matter that you are consistent, and whichever URL you used to register is what you use to provide as callback (redirect).

The reason is in the spec and according to OAauth2 seicifcation the authorization server will check the redirect uri match using a simple string comparison - see here. Therefore even one letter difference matters even if these urls dns resolution would end up being the same server.

0
httPants On

The spring-authorization-server documentation has a specific example that demonstrates how to configure a custom authentication validator that allows for localhost in the redirect_uri parameter here

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
        new OAuth2AuthorizationServerConfigurer();
    http.apply(authorizationServerConfigurer);

    authorizationServerConfigurer
        .authorizationEndpoint(authorizationEndpoint ->
            authorizationEndpoint
                .authenticationProviders(configureAuthenticationValidator())
        );

    return http.build();
}

private Consumer<List<AuthenticationProvider>> configureAuthenticationValidator() {
    return (authenticationProviders) ->
        authenticationProviders.forEach((authenticationProvider) -> {
            if (authenticationProvider instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider) {
                Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> authenticationValidator =
                    // Override default redirect_uri validator
                    new CustomRedirectUriValidator()
                        // Reuse default scope validator
                        .andThen(OAuth2AuthorizationCodeRequestAuthenticationValidator.DEFAULT_SCOPE_VALIDATOR);

                ((OAuth2AuthorizationCodeRequestAuthenticationProvider) authenticationProvider)
                    .setAuthenticationValidator(authenticationValidator);
            }
        });
}

static class CustomRedirectUriValidator implements Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> {

    @Override
    public void accept(OAuth2AuthorizationCodeRequestAuthenticationContext authenticationContext) {
        OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication =
            authenticationContext.getAuthentication();
        RegisteredClient registeredClient = authenticationContext.getRegisteredClient();
        String requestedRedirectUri = authorizationCodeRequestAuthentication.getRedirectUri();

        // Use exact string matching when comparing client redirect URIs against pre-registered URIs
        if (!registeredClient.getRedirectUris().contains(requestedRedirectUri)) {
            OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST);
            throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);
        }
    }
}