private Mono<Map<String, OAuth2AuthorizationRequest>> getStateToAuthorizationRequest(ServerWebExchange exchange, boolean create) { Assert.notNull(exchange, "exchange cannot be null"); return getSessionAttributes(exchange) .doOnNext(sessionAttrs -> { if (create) { sessionAttrs.putIfAbsent(this.sessionAttributeName, new HashMap<String, OAuth2AuthorizationRequest>()); } }) .flatMap(sessionAttrs -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs))); }
@Override public Mono<OAuth2AuthorizationRequest> loadAuthorizationRequest( ServerWebExchange exchange) { String state = getStateParameter(exchange); if (state == null) { return Mono.empty(); } return getStateToAuthorizationRequest(exchange, false) .filter(stateToAuthorizationRequest -> stateToAuthorizationRequest.containsKey(state)) .map(stateToAuthorizationRequest -> stateToAuthorizationRequest.get(state)); }
@Test public void loadAuthorizatioNRequestWhenNullExchangeThenIllegalArgumentException() { this.exchange = null; assertThatThrownBy(() -> this.repository.loadAuthorizationRequest(this.exchange)) .isInstanceOf(IllegalArgumentException.class); }
@Override public Mono<OAuth2AuthorizationRequest> removeAuthorizationRequest( ServerWebExchange exchange) { String state = getStateParameter(exchange); if (state == null) { return Mono.empty(); } return exchange.getSession() .map(WebSession::getAttributes) .handle((sessionAttrs, sink) -> { Map<String, OAuth2AuthorizationRequest> stateToAuthzRequest = sessionAttrsMapStateToAuthorizationRequest(sessionAttrs); if (stateToAuthzRequest == null) { sink.complete(); return; } OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state); if (stateToAuthzRequest.isEmpty()) { sessionAttrs.remove(this.sessionAttributeName); } if (removedValue == null) { sink.complete(); } else { sink.next(removedValue); } }); }
@Test public void removeAuthorizationRequestWhenMultipleThenOnlyOneRemoved() { String oldState = "state0"; MockServerHttpRequest oldRequest = MockServerHttpRequest.get("/") .queryParam(OAuth2ParameterNames.STATE, oldState).build(); OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .authorizationUri("https://example.com/oauth2/authorize") .clientId("client-id") .redirectUri("http://localhost/client-1") .state(oldState) .build(); WebSessionManager sessionManager = e -> this.exchange.getSession(); this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); Mono<OAuth2AuthorizationRequest> saveAndSaveAndRemove = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) .then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange)) .then(this.repository.removeAuthorizationRequest(this.exchange)); StepVerifier.create(saveAndSaveAndRemove) .expectNext(this.authorizationRequest) .verifyComplete(); StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)) .verifyComplete(); StepVerifier.create(this.repository.loadAuthorizationRequest(oldExchange)) .expectNext(oldAuthorizationRequest) .verifyComplete(); }
@Test public void loadAuthorizationRequestWhenSavedThenAuthorizationRequest() { Mono<OAuth2AuthorizationRequest> saveAndLoad = this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.loadAuthorizationRequest(this.exchange)); StepVerifier.create(saveAndLoad) .expectNext(this.authorizationRequest) .verifyComplete(); }
@Override public Mono<Void> saveAuthorizationRequest( OAuth2AuthorizationRequest authorizationRequest, ServerWebExchange exchange) { Assert.notNull(authorizationRequest, "authorizationRequest cannot be null"); return getStateToAuthorizationRequest(exchange, true) .doOnNext(stateToAuthorizationRequest -> stateToAuthorizationRequest.put(authorizationRequest.getState(), authorizationRequest)) .then(); }
@Test public void removeAuthorizationRequestWhenPresentThenFoundAndRemoved() { Mono<OAuth2AuthorizationRequest> saveAndRemove = this.repository .saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.removeAuthorizationRequest(this.exchange)); StepVerifier.create(saveAndRemove).expectNext(this.authorizationRequest) .verifyComplete(); StepVerifier.create(this.exchange.getSession() .map(WebSession::getAttributes) .map(Map::isEmpty)) .expectNext(true) .verifyComplete(); }
@Test public void saveAuthorizationRequestWhenExchangeNullThenThrowsIllegalArgumentException() { this.exchange = null; assertThatThrownBy(() -> this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange)) .isInstanceOf(IllegalArgumentException.class); }
@Test public void removeAuthorizationRequestWhenExchangeNullThenThrowsIllegalArgumentException() { this.exchange = null; assertThatThrownBy(() -> this.repository.removeAuthorizationRequest(this.exchange)) .isInstanceOf(IllegalArgumentException.class); }
@Override public Mono<OAuth2AuthorizationRequest> removeAuthorizationRequest( ServerWebExchange exchange) { String state = getStateParameter(exchange); if (state == null) { return Mono.empty(); } return exchange.getSession() .map(WebSession::getAttributes) .handle((sessionAttrs, sink) -> { Map<String, OAuth2AuthorizationRequest> stateToAuthzRequest = sessionAttrsMapStateToAuthorizationRequest(sessionAttrs); if (stateToAuthzRequest == null) { sink.complete(); return; } OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state); if (stateToAuthzRequest.isEmpty()) { sessionAttrs.remove(this.sessionAttributeName); } if (removedValue == null) { sink.complete(); } else { sink.next(removedValue); } }); }
@Test public void loadAuthorizationRequestWhenNoStateParamThenEmpty() { this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); Mono<OAuth2AuthorizationRequest> saveAndLoad = this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.loadAuthorizationRequest(this.exchange)); StepVerifier.create(saveAndLoad) .verifyComplete(); }
@Override public Mono<Void> saveAuthorizationRequest( OAuth2AuthorizationRequest authorizationRequest, ServerWebExchange exchange) { Assert.notNull(authorizationRequest, "authorizationRequest cannot be null"); return getStateToAuthorizationRequest(exchange, true) .doOnNext(stateToAuthorizationRequest -> stateToAuthorizationRequest.put(authorizationRequest.getState(), authorizationRequest)) .then(); }
@Test public void removeAuthorizationRequestWhenStateMissingThenNoErrors() { MockServerHttpRequest otherState = MockServerHttpRequest.get("/") .queryParam(OAuth2ParameterNames.STATE, "other") .build(); ServerWebExchange otherStateExchange = this.exchange.mutate() .request(otherState) .build(); Mono<OAuth2AuthorizationRequest> saveAndRemove = this.repository .saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.removeAuthorizationRequest(otherStateExchange)); StepVerifier.create(saveAndRemove) .verifyComplete(); }
@Test public void saveAuthorizationRequestWhenAuthorizationRequestNullThenThrowsIllegalArgumentException() { this.authorizationRequest = null; assertThatThrownBy(() -> this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange)) .isInstanceOf(IllegalArgumentException.class); assertSessionStartedIs(false); }
@Test public void removeAuthorizationRequestWhenNotPresentThenThrowsIllegalArgumentException() { StepVerifier.create(this.repository.removeAuthorizationRequest(this.exchange)) .verifyComplete(); assertSessionStartedIs(false); }
private Mono<Map<String, OAuth2AuthorizationRequest>> getStateToAuthorizationRequest(ServerWebExchange exchange, boolean create) { Assert.notNull(exchange, "exchange cannot be null"); return getSessionAttributes(exchange) .doOnNext(sessionAttrs -> { if (create) { sessionAttrs.putIfAbsent(this.sessionAttributeName, new HashMap<String, OAuth2AuthorizationRequest>()); } }) .flatMap(sessionAttrs -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs))); }
@Override public Mono<OAuth2AuthorizationRequest> loadAuthorizationRequest( ServerWebExchange exchange) { String state = getStateParameter(exchange); if (state == null) { return Mono.empty(); } return getStateToAuthorizationRequest(exchange, false) .filter(stateToAuthorizationRequest -> stateToAuthorizationRequest.containsKey(state)) .map(stateToAuthorizationRequest -> stateToAuthorizationRequest.get(state)); }
@Test public void loadAuthorizationRequestWhenMultipleSavedThenAuthorizationRequest() { String oldState = "state0"; MockServerHttpRequest oldRequest = MockServerHttpRequest.get("/") .queryParam(OAuth2ParameterNames.STATE, oldState).build(); OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .authorizationUri("https://example.com/oauth2/authorize") .clientId("client-id") .redirectUri("http://localhost/client-1") .state(oldState) .build(); WebSessionManager sessionManager = e -> this.exchange.getSession(); this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); Mono<OAuth2AuthorizationRequest> saveAndSaveAndLoad = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) .then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange)) .then(this.repository.loadAuthorizationRequest(oldExchange)); StepVerifier.create(saveAndSaveAndLoad) .expectNext(oldAuthorizationRequest) .verifyComplete(); StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)) .expectNext(this.authorizationRequest) .verifyComplete(); }
@Test public void loadAuthorizationRequestWhenSessionAndNoRequestThenEmpty() { Mono<OAuth2AuthorizationRequest> setAttrThenLoad = this.exchange.getSession() .map(WebSession::getAttributes).doOnNext(attrs -> attrs.put("foo", "bar")) .then(this.repository.loadAuthorizationRequest(this.exchange)); StepVerifier.create(setAttrThenLoad) .verifyComplete(); }