Skip to content

Commit

Permalink
fix: pass ex message to InvalidGrantException message
Browse files Browse the repository at this point in the history
fixes AM-4731
  • Loading branch information
lgw-gravitee committed Feb 10, 2025
1 parent d6baadb commit bea5257
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@
*/
public class InvalidGrantException extends OAuth2Exception {

public InvalidGrantException() {
super();
}

public InvalidGrantException(String message) {
super(message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ protected Single<TokenRequest> parseRequest(TokenRequest tokenRequest, Client cl
@Override
protected Maybe<User> resolveResourceOwner(TokenRequest tokenRequest, Client client) {
return userAuthenticationManager.loadPreAuthenticatedUser(tokenRequest.getSubject(), tokenRequest)
.onErrorResumeNext(ex -> { return Maybe.error(new InvalidGrantException()); });
.onErrorResumeNext(ex -> Maybe.error(new InvalidGrantException(ex.getMessage())));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ protected Single<TokenRequest> parseRequest(TokenRequest tokenRequest, Client cl
@Override
protected Maybe<User> resolveResourceOwner(TokenRequest tokenRequest, Client client) {
return userAuthenticationManager.loadPreAuthenticatedUser(tokenRequest.getSubject(), tokenRequest)
.onErrorResumeNext(ex -> { return Maybe.error(new InvalidGrantException()); });
.onErrorResumeNext(ex -> Maybe.error(new InvalidGrantException(ex.getMessage())));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.gravitee.am.model.oidc.Client;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Single;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -160,7 +161,8 @@ protected Maybe<User> resolveResourceOwner(TokenRequest tokenRequest, Client cli
}
})
.onErrorResumeNext(ex -> {
return Maybe.error(new InvalidGrantException(ex.getMessage()));
String msg = StringUtils.isBlank(ex.getMessage()) ? "Unknown error" : ex.getMessage();
return Maybe.error(new InvalidGrantException(msg));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected Maybe<User> resolveResourceOwner(TokenRequest tokenRequest, Client cli
}

return userAuthenticationManager.loadPreAuthenticatedUser(subject, tokenRequest)
.onErrorResumeNext(ex -> { return Maybe.error(new InvalidGrantException()); });
.onErrorResumeNext(ex -> Maybe.error(new InvalidGrantException(ex.getMessage())));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public void handle(RoutingContext routingContext) {
}
});

when(revocationTokenService.revoke(any(), any())).thenReturn(Completable.error(new InvalidGrantException()));
when(revocationTokenService.revoke(any(), any())).thenReturn(Completable.error(new InvalidGrantException("error message")));

testRequest(
HttpMethod.POST, "/oauth/revoke?token=toto",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.gravitee.am.gateway.handler.oauth2.service.granter.code;

import io.gravitee.am.common.oauth2.Parameters;
import io.gravitee.am.gateway.handler.common.auth.user.UserAuthenticationManager;
import io.gravitee.am.gateway.handler.common.policy.RulesEngine;
import io.gravitee.am.gateway.handler.oauth2.service.code.AuthorizationCodeService;
import io.gravitee.am.gateway.handler.oauth2.service.request.TokenRequest;
import io.gravitee.am.gateway.handler.oauth2.service.request.TokenRequestResolver;
import io.gravitee.am.gateway.handler.oauth2.service.token.Token;
import io.gravitee.am.gateway.handler.oauth2.service.token.TokenService;
import io.gravitee.am.model.AuthenticationFlowContext;
import io.gravitee.am.model.oidc.Client;
import io.gravitee.am.repository.oauth2.model.AuthorizationCode;
import io.gravitee.am.service.AuthenticationFlowContextService;
import io.gravitee.common.util.LinkedMultiValueMap;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.observers.TestObserver;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.core.env.Environment;

import java.util.concurrent.TimeUnit;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class AuthorizationCodeTokenGranterTest {


@Mock
private TokenRequestResolver tokenRequestResolver;

@Mock
private TokenService tokenService;

@Mock
private AuthorizationCodeService authorizationCodeService;

@Mock
private UserAuthenticationManager userAuthenticationManager;

@Mock
private AuthenticationFlowContextService authenticationFlowContextService;

@Mock
private Environment env;

@Mock
private RulesEngine rulesEngine;


private AuthorizationCodeTokenGranter granter;

@Before
public void init() {
Mockito.when(env.getProperty(any(), Mockito.eq(Boolean.class), any())).thenReturn(true);
granter = new AuthorizationCodeTokenGranter(tokenRequestResolver, tokenService, authorizationCodeService, userAuthenticationManager, authenticationFlowContextService, env, rulesEngine);
}

@Test
public void the_exception_message_should_be_propagated_to_granter() {
AuthorizationCode authorizationCode = new AuthorizationCode();
authorizationCode.setRequestParameters(new LinkedMultiValueMap<>());
Mockito.when(authorizationCodeService.remove(any(), any())).thenReturn(Maybe.just(authorizationCode));
Mockito.when(authenticationFlowContextService.removeContext(any(), Mockito.anyInt())).thenReturn(Maybe.just(new AuthenticationFlowContext()));
Mockito.when(userAuthenticationManager.loadPreAuthenticatedUser(any(), any())).thenReturn(Maybe.error(new RuntimeException("unknown error")));
TokenRequest tokenRequest = Mockito.mock();

LinkedMultiValueMap values = new LinkedMultiValueMap<>();
when(tokenRequest.parameters()).thenReturn(values);
values.add(Parameters.CODE, "xxxxx");

final TestObserver<Token> test = granter.grant(tokenRequest, mock(Client.class)).test();
test.awaitDone(10, TimeUnit.SECONDS);
test.assertError(ex -> ex.getMessage().equals("unknown error"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.gravitee.am.gateway.handler.oauth2.service.granter.extensiongrant;

import io.gravitee.am.extensiongrant.api.ExtensionGrantProvider;
import io.gravitee.am.gateway.handler.common.vertx.core.http.VertxHttpHeaders;
import io.gravitee.am.gateway.handler.oauth2.service.request.TokenRequest;
import io.gravitee.am.model.ExtensionGrant;
import io.gravitee.am.model.oidc.Client;
import io.reactivex.rxjava3.core.Maybe;
import io.vertx.core.http.impl.headers.HeadersMultiMap;
import org.junit.Test;
import org.mockito.Mockito;


public class ExtensionGrantGranterTest {

@Test
public void when_ex_msg_is_missing_present_default_one(){
ExtensionGrantProvider extensionGrantProvider = Mockito.mock();
ExtensionGrant extensionGrant = new ExtensionGrant();
extensionGrant.setGrantType("jwt-bearer");

ExtensionGrantGranter granter = new ExtensionGrantGranter(
extensionGrantProvider,
extensionGrant,
Mockito.mock(),
Mockito.mock(),
Mockito.mock(),
Mockito.mock(),
Mockito.mock(),
Mockito.mock());

TokenRequest tokenRequest = new TokenRequest();
tokenRequest.setParameters(new VertxHttpHeaders(new HeadersMultiMap()));
Client client = new Client();

Mockito.when(extensionGrantProvider.grant(Mockito.any())).thenReturn(Maybe.error(new RuntimeException("")));

granter.resolveResourceOwner(tokenRequest, client)
.test()
.assertError(ex -> ex.getMessage().equals("Unknown error"));

}

@Test
public void when_ex_msg_is_present_return_it(){
ExtensionGrantProvider extensionGrantProvider = Mockito.mock();
ExtensionGrant extensionGrant = new ExtensionGrant();
extensionGrant.setGrantType("jwt-bearer");

ExtensionGrantGranter granter = new ExtensionGrantGranter(
extensionGrantProvider,
extensionGrant,
Mockito.mock(),
Mockito.mock(),
Mockito.mock(),
Mockito.mock(),
Mockito.mock(),
Mockito.mock());

TokenRequest tokenRequest = new TokenRequest();
tokenRequest.setParameters(new VertxHttpHeaders(new HeadersMultiMap()));
Client client = new Client();

Mockito.when(extensionGrantProvider.grant(Mockito.any())).thenReturn(Maybe.error(new RuntimeException("message")));

granter.resolveResourceOwner(tokenRequest, client)
.test()
.assertError(ex -> ex.getMessage().equals("message"));

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public void shouldNotGenerateAnAccessToken_invalidGrant() {

when(tokenRequest.parameters()).thenReturn(parameters);

when(tokenService.refresh(refreshToken, tokenRequest, client)).thenReturn(Single.error(new InvalidGrantException()));
when(tokenService.refresh(refreshToken, tokenRequest, client)).thenReturn(Single.error(new InvalidGrantException("error message")));

granter.grant(tokenRequest, client).test().assertError(InvalidGrantException.class);
}
Expand Down

0 comments on commit bea5257

Please sign in to comment.