/*
* Copyright 2013-2017 the original author or authors.
*
* 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 org.cloudfoundry.reactor.uaa.tokens;
import org.cloudfoundry.reactor.InteractionContext;
import org.cloudfoundry.reactor.TestRequest;
import org.cloudfoundry.reactor.TestResponse;
import org.cloudfoundry.reactor.uaa.AbstractUaaApiTest;
import org.cloudfoundry.uaa.tokens.CheckTokenRequest;
import org.cloudfoundry.uaa.tokens.CheckTokenResponse;
import org.cloudfoundry.uaa.tokens.GetTokenByAuthorizationCodeRequest;
import org.cloudfoundry.uaa.tokens.GetTokenByAuthorizationCodeResponse;
import org.cloudfoundry.uaa.tokens.GetTokenByClientCredentialsRequest;
import org.cloudfoundry.uaa.tokens.GetTokenByClientCredentialsResponse;
import org.cloudfoundry.uaa.tokens.GetTokenByOneTimePasscodeRequest;
import org.cloudfoundry.uaa.tokens.GetTokenByOneTimePasscodeResponse;
import org.cloudfoundry.uaa.tokens.GetTokenByOpenIdRequest;
import org.cloudfoundry.uaa.tokens.GetTokenByOpenIdResponse;
import org.cloudfoundry.uaa.tokens.GetTokenByPasswordRequest;
import org.cloudfoundry.uaa.tokens.GetTokenByPasswordResponse;
import org.cloudfoundry.uaa.tokens.GetTokenKeyRequest;
import org.cloudfoundry.uaa.tokens.GetTokenKeyResponse;
import org.cloudfoundry.uaa.tokens.KeyType;
import org.cloudfoundry.uaa.tokens.ListTokenKeysRequest;
import org.cloudfoundry.uaa.tokens.ListTokenKeysResponse;
import org.cloudfoundry.uaa.tokens.RefreshTokenRequest;
import org.cloudfoundry.uaa.tokens.RefreshTokenResponse;
import org.cloudfoundry.uaa.tokens.TokenFormat;
import org.cloudfoundry.uaa.tokens.TokenKey;
import org.junit.Test;
import reactor.test.StepVerifier;
import java.time.Duration;
import java.util.Arrays;
import static io.netty.handler.codec.http.HttpMethod.GET;
import static io.netty.handler.codec.http.HttpMethod.POST;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
public final class ReactorTokensTest extends AbstractUaaApiTest {
private final ReactorTokens tokens = new ReactorTokens(CONNECTION_CONTEXT, this.root, TOKEN_PROVIDER);
@Test
public void check() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(POST).path("/check_token?scopes=password.write,scim.userids&token=f9f2f98d88e04ff7bb1f69041d3c0346")
.header("Authorization", "Basic YXBwOmFwcGNsaWVudHNlY3JldA==")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/check/POST_response.json")
.build())
.build());
this.tokens
.check(CheckTokenRequest.builder()
.token("f9f2f98d88e04ff7bb1f69041d3c0346")
.scope("password.write")
.scope("scim.userids")
.clientId("app")
.clientSecret("appclientsecret")
.build())
.as(StepVerifier::create)
.expectNext(CheckTokenResponse.builder()
.userId("ae77988e-1b25-4e02-87f2-81f98293a356")
.userName("marissa")
.email("marissa@test.org")
.clientId("app")
.expirationTime(1462015244L)
.scopes(Arrays.asList("scim.userids", "openid", "cloud_controller.read", "password.write", "cloud_controller.write"))
.jwtId("f9f2f98d88e04ff7bb1f69041d3c0346")
.audiences(Arrays.asList("app", "scim", "openid", "cloud_controller", "password"))
.subject("ae77988e-1b25-4e02-87f2-81f98293a356")
.issuer("http://localhost:8080/uaa/oauth/token")
.issuedAt(1461972044L)
.cid("app")
.grantType("password")
.authorizedParty("app")
.authorizationTime(1461972044L)
.zoneId("uaa")
.revocationSignature("4e89e4da")
.origin("uaa")
.revocable(true)
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void getKey() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(GET).path("/token_key")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/token_key/GET_response.json")
.build())
.build());
this.tokens
.getKey(GetTokenKeyRequest.builder()
.build())
.as(StepVerifier::create)
.expectNext(GetTokenKeyResponse.builder()
.id("testKey")
.algorithm("SHA256withRSA")
.value("-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO\n" +
"rn2dVQ3vfBJqcDuFUK03d+1PZGbVlNCqnkpIJ8syFppW8ljnWweP7+LiWpRoz0I7\n" +
"fYb3d8TjhV86Y997Fl4DBrxgM6KTJOuE/uxnoDhZQ14LgOU2ckXjOzOdTsnGMKQB\n" +
"LCl0vpcXBtFLMaSbpv1ozi8h7DJyVZ6EnFQZUWGdgTMhDrmqevfx95U/16c5WBDO\n" +
"kqwIn7Glry9n9Suxygbf8g5AzpWcusZgDLIIZ7JTUldBb8qU2a0Dl4mvLZOn4wPo\n" +
"jfj9Cw2QICsc5+Pwf21fP+hzf+1WSRHbnYv8uanRO0gZ8ekGaghM/2H6gqJbo2nI\n" +
"JwIDAQAB\n" +
"-----END PUBLIC KEY-----")
.keyType(KeyType.RSA)
.use("sig")
.n("ANJufZdrvYg5zG61x36pDq59nVUN73wSanA7hVCtN3ftT2Rm1ZTQqp5KSCfLMhaaVvJY51sHj" +
"+/i4lqUaM9CO32G93fE44VfOmPfexZeAwa8YDOikyTrhP7sZ6A4WUNeC4DlNnJF4zsznU7JxjCkASwpdL6XFwbRSzGkm6b9aM4vIewyclWehJxUGVFhnYEzIQ65qnr38feVP9enOVgQzpKsCJ+xpa8vZ/UrscoG3" +
"/IOQM6VnLrGYAyyCGeyU1JXQW/KlNmtA5eJry2Tp+MD6I34/QsNkCArHOfj8H9tXz/oc3/tVkkR252L/Lmp0TtIGfHpBmoITP9h+oKiW6NpyCc=")
.e("AQAB")
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void getTokenByAuthorizationCode() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(POST).path("/oauth/token?code=zI6Z1X&client_id=login&client_secret=loginsecret&redirect_uri=https://uaa.cloudfoundry.com/redirect/cf" +
"&token_format=opaque&grant_type=authorization_code&response_type=token")
.header("Authorization", null)
.header("Content-Type", "application/x-www-form-urlencoded")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/tokens/GET_response_AC.json")
.build())
.build());
this.tokens
.getByAuthorizationCode(GetTokenByAuthorizationCodeRequest.builder()
.clientId("login")
.clientSecret("loginsecret")
.authorizationCode("zI6Z1X")
.redirectUri("https://uaa.cloudfoundry.com/redirect/cf")
.tokenFormat(TokenFormat.OPAQUE)
.build())
.as(StepVerifier::create)
.expectNext(GetTokenByAuthorizationCodeResponse.builder()
.accessToken("555e2047bbc849628ff8cbfa7b342274")
.tokenType("bearer")
.refreshToken("555e2047bbc849628ff8cbfa7b342274-r")
.expiresInSeconds(43199)
.scopes("openid oauth.approvals")
.tokenId("555e2047bbc849628ff8cbfa7b342274")
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void getTokenByClientCredentials() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(POST).path("/oauth/token?client_id=login&client_secret=loginsecret&token_format=opaque&grant_type=client_credentials&response_type=token")
.header("Authorization", null)
.header("Content-Type", "application/x-www-form-urlencoded")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/tokens/GET_response_CC.json")
.build())
.build());
this.tokens
.getByClientCredentials(GetTokenByClientCredentialsRequest.builder()
.clientId("login")
.clientSecret("loginsecret")
.tokenFormat(TokenFormat.OPAQUE)
.build())
.as(StepVerifier::create)
.expectNext(GetTokenByClientCredentialsResponse.builder()
.accessToken("f87f93a2666d4e6eaa54e34df86d160c")
.tokenType("bearer")
.expiresInSeconds(43199)
.scopes("clients.read emails.write scim.userids password.write idps.write notifications.write oauth.login scim.write critical_notifications.write")
.tokenId("f87f93a2666d4e6eaa54e34df86d160c")
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void getTokenByOneTimePasscode() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(POST).path("/oauth/token?client_id=app&client_secret=appclientsecret&passcode=qcZNkd&token_format=opaque&grant_type=password&response_type=token")
.header("Authorization", null)
.header("Content-Type", "application/x-www-form-urlencoded")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/tokens/GET_response_OT.json")
.build())
.build());
this.tokens
.getByOneTimePasscode(GetTokenByOneTimePasscodeRequest.builder()
.clientId("app")
.clientSecret("appclientsecret")
.passcode("qcZNkd")
.tokenFormat(TokenFormat.OPAQUE)
.build())
.as(StepVerifier::create)
.expectNext(GetTokenByOneTimePasscodeResponse.builder()
.accessToken("0ddcada64ef742a28badaf4750ef435f")
.tokenType("bearer")
.refreshToken("0ddcada64ef742a28badaf4750ef435f-r")
.expiresInSeconds(43199)
.scopes("scim.userids openid cloud_controller.read password.write cloud_controller.write")
.tokenId("0ddcada64ef742a28badaf4750ef435f")
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void getTokenByOpenId() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(POST).path("/oauth/token?code=NAlA1d&client_id=app&client_secret=appclientsecret&redirect_uri=https://uaa.cloudfoundry.com/redirect/cf&token_format=opaque" +
"&grant_type=authorization_code&response_type=id_token")
.header("Authorization", null)
.header("Content-Type", "application/x-www-form-urlencoded")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/tokens/GET_response_OI.json")
.build())
.build());
this.tokens
.getByOpenId(GetTokenByOpenIdRequest.builder()
.clientId("app")
.clientSecret("appclientsecret")
.authorizationCode("NAlA1d")
.redirectUri("https://uaa.cloudfoundry.com/redirect/cf")
.tokenFormat(TokenFormat.OPAQUE)
.build())
.as(StepVerifier::create)
.expectNext(GetTokenByOpenIdResponse.builder()
.accessToken("53a58e6581ee49d08f9e572f673bc8db")
.tokenType("bearer")
.openIdToken("eyJhbGciOiJIUzI1NiIsImtpZCI6ImxlZ2FjeS10b2tlbi1rZXkiLC")
.refreshToken("53a58e6581ee49d08f9e572f673bc8db-r")
.expiresInSeconds(43199)
.scopes("openid oauth.approvals")
.tokenId("53a58e6581ee49d08f9e572f673bc8db")
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void getTokenByPassword() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(POST).path("/oauth/token?client_id=app&client_secret=appclientsecret&password=secr3T&token_format=opaque&" +
"username=jENeJj@test.org&grant_type=password&response_type=token")
.header("Authorization", null)
.header("Content-Type", "application/x-www-form-urlencoded")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/tokens/GET_response_PW.json")
.build())
.build());
this.tokens
.getByPassword(GetTokenByPasswordRequest.builder()
.clientId("app")
.clientSecret("appclientsecret")
.password("secr3T")
.tokenFormat(TokenFormat.OPAQUE)
.username("jENeJj@test.org")
.build())
.as(StepVerifier::create)
.expectNext(GetTokenByPasswordResponse.builder()
.accessToken("cd37a35114084fafb83d21c6f2af0e84")
.tokenType("bearer")
.refreshToken("cd37a35114084fafb83d21c6f2af0e84-r")
.expiresInSeconds(43199)
.scopes("scim.userids openid cloud_controller.read password.write cloud_controller.write")
.tokenId("cd37a35114084fafb83d21c6f2af0e84")
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void listKeys() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(GET).path("/token_keys")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/token_keys/GET_response.json")
.build())
.build());
this.tokens
.listKeys(ListTokenKeysRequest.builder()
.build())
.as(StepVerifier::create)
.expectNext(ListTokenKeysResponse.builder()
.key(TokenKey.builder()
.id("testKey")
.algorithm("SHA256withRSA")
.value("-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO\n" +
"rn2dVQ3vfBJqcDuFUK03d+1PZGbVlNCqnkpIJ8syFppW8ljnWweP7+LiWpRoz0I7\n" +
"fYb3d8TjhV86Y997Fl4DBrxgM6KTJOuE/uxnoDhZQ14LgOU2ckXjOzOdTsnGMKQB\n" +
"LCl0vpcXBtFLMaSbpv1ozi8h7DJyVZ6EnFQZUWGdgTMhDrmqevfx95U/16c5WBDO\n" +
"kqwIn7Glry9n9Suxygbf8g5AzpWcusZgDLIIZ7JTUldBb8qU2a0Dl4mvLZOn4wPo\n" +
"jfj9Cw2QICsc5+Pwf21fP+hzf+1WSRHbnYv8uanRO0gZ8ekGaghM/2H6gqJbo2nI\n" +
"JwIDAQAB\n" +
"-----END PUBLIC KEY-----")
.keyType(KeyType.RSA)
.use("sig")
.n("ANJufZdrvYg5zG61x36pDq59nVUN73wSanA7hVCtN3ftT2Rm1ZTQqp5KSCfLMhaaVvJY51sHj" +
"+/i4lqUaM9CO32G93fE44VfOmPfexZeAwa8YDOikyTrhP7sZ6A4WUNeC4DlNnJF4zsznU7JxjCkASwpdL6XFwbRSzGkm6b9aM4vIewyclWehJxUGVFhnYEzIQ65qnr38feVP9enOVgQzpKsCJ+xpa8vZ/UrscoG3" +
"/IOQM6VnLrGYAyyCGeyU1JXQW/KlNmtA5eJry2Tp+MD6I34/QsNkCArHOfj8H9tXz/oc3/tVkkR252L/Lmp0TtIGfHpBmoITP9h+oKiW6NpyCc=")
.e("AQAB")
.build())
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
@Test
public void refreshToken() {
mockRequest(InteractionContext.builder()
.request(TestRequest.builder()
.method(POST).path("/oauth/token?client_id=app&client_secret=appclientsecret&refresh_token=6af5fc07a8b74c2eafb0079ff477bb11-r&token_format=opaque&grant_type=refresh_token")
.build())
.response(TestResponse.builder()
.status(OK)
.payload("fixtures/uaa/tokens/GET_refresh_response.json")
.build())
.build());
this.tokens
.refresh(RefreshTokenRequest.builder()
.clientId("app")
.clientSecret("appclientsecret")
.refreshToken("6af5fc07a8b74c2eafb0079ff477bb11-r")
.tokenFormat(TokenFormat.OPAQUE)
.build())
.as(StepVerifier::create)
.expectNext(RefreshTokenResponse.builder()
.accessToken("eyJhbGciOiJIUzI1NiIsImtpZCI6Imx")
.tokenType("bearer")
.refreshToken("eyJhbGciOiJIUzI1NiIsImtpZCI6Imx_E")
.expiresInSeconds(43199)
.scopes("scim.userids cloud_controller.read password.write cloud_controller.write openid")
.tokenId("6af5fc07a8b74c2eafb0079ff477bb11")
.build())
.expectComplete()
.verify(Duration.ofSeconds(5));
}
}