Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: New endpoint for get JWT of SSA based on JTI #3724

Merged
merged 1 commit into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text.
*
* Copyright (c) 2020, Janssen Project
*/

package io.jans.as.client.ssa.jwtssa;

import io.jans.as.client.BaseClient;
import io.jans.as.model.config.Constants;
import jakarta.ws.rs.HttpMethod;
import jakarta.ws.rs.client.Invocation.Builder;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;

public class SsaGetJwtClient extends BaseClient<SsaGetJwtRequest, SsaGetJwtResponse> {

private static final Logger log = Logger.getLogger(SsaGetJwtClient.class);

public SsaGetJwtClient(String url) {
super(url + "/jwt");
}

@Override
public String getHttpMethod() {
return HttpMethod.GET;
}

public SsaGetJwtResponse execGetJwtSsa(@NotNull String accessToken, @NotNull String jti) {
SsaGetJwtRequest ssaGetRequest = new SsaGetJwtRequest();
ssaGetRequest.setJti(jti);
ssaGetRequest.setAccessToken(accessToken);
setRequest(ssaGetRequest);
return exec();
}

public SsaGetJwtResponse exec() {
try {
initClient();
String uriWithParams = getUrl() + "?" + getRequest().getQueryString();
Builder clientRequest = resteasyClient.target(uriWithParams).request();
applyCookies(clientRequest);

clientRequest.header("Content-Type", request.getContentType());
if (StringUtils.isNotBlank(request.getAccessToken())) {
clientRequest.header(Constants.AUTHORIZATION, "Bearer ".concat(request.getAccessToken()));
}

clientResponse = clientRequest.build(getHttpMethod()).invoke();
final SsaGetJwtResponse res = new SsaGetJwtResponse(clientResponse);
res.injectDataFromJson();
setResponse(res);

} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
closeConnection();
}

return getResponse();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text.
*
* Copyright (c) 2020, Janssen Project
*/

package io.jans.as.client.ssa.jwtssa;

import io.jans.as.client.BaseRequest;
import io.jans.as.model.common.AuthorizationMethod;
import io.jans.as.model.ssa.SsaRequestParam;
import io.jans.as.model.util.QueryBuilder;
import jakarta.ws.rs.core.MediaType;

public class SsaGetJwtRequest extends BaseRequest {

private String jti;

private String accessToken;

public SsaGetJwtRequest() {
setContentType(MediaType.APPLICATION_JSON);
setMediaType(MediaType.APPLICATION_JSON);
setAuthorizationMethod(AuthorizationMethod.AUTHORIZATION_REQUEST_HEADER_FIELD);
}

public String getJti() {
return jti;
}

public void setJti(String jti) {
this.jti = jti;
}

public String getAccessToken() {
return accessToken;
}

public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

@Override
public String getQueryString() {
QueryBuilder builder = QueryBuilder.instance();
builder.append(SsaRequestParam.JTI.getName(), jti);
return builder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text.
*
* Copyright (c) 2020, Janssen Project
*/

package io.jans.as.client.ssa.jwtssa;

import io.jans.as.client.BaseResponseWithErrors;
import io.jans.as.model.ssa.SsaErrorResponseType;
import jakarta.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;

import static io.jans.as.model.ssa.SsaRequestParam.SSA;

public class SsaGetJwtResponse extends BaseResponseWithErrors<SsaErrorResponseType> {

private static final Logger log = Logger.getLogger(SsaGetJwtResponse.class);

private String ssa;

public SsaGetJwtResponse(Response clientResponse) {
super(clientResponse);
}

@Override
public SsaErrorResponseType fromString(String p_str) {
return SsaErrorResponseType.fromString(p_str);
}

public void injectDataFromJson() {
injectDataFromJson(entity);
}

@Override
public void injectDataFromJson(String json) {
if (StringUtils.isNotBlank(entity)) {
try {
JSONObject jsonObj = new JSONObject(entity);
if (jsonObj.has(SSA.getName())) {
ssa = jsonObj.getString(SSA.getName());
}
} catch (JSONException e) {
log.error("Error on inject data from json: " + e.getMessage(), e);
}
}
}

public String getSsa() {
return ssa;
}

public void setSsa(String ssa) {
this.ssa = ssa;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.jans.as.client.ssa.create.SsaCreateRequest;
import io.jans.as.client.ssa.create.SsaCreateResponse;
import io.jans.as.client.ssa.get.SsaGetResponse;
import io.jans.as.client.ssa.jwtssa.SsaGetJwtResponse;
import io.jans.as.model.exception.InvalidJwtException;
import io.jans.as.model.jwe.Jwe;
import io.jans.as.model.jwt.Jwt;
Expand Down Expand Up @@ -65,4 +66,8 @@ public static SsaCreateAssertBuilder ssaCreate(SsaCreateRequest request, SsaCrea
public static SsaGetAssertBuilder ssaGet(SsaGetResponse response) {
return new SsaGetAssertBuilder(response);
}

public static SsaGetJwtAssertBuilder ssaGetJwt(SsaGetJwtResponse response) {
return new SsaGetJwtAssertBuilder(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.jans.as.client.client.assertbuilders;

import io.jans.as.client.ssa.jwtssa.SsaGetJwtResponse;
import io.jans.as.model.jwt.Jwt;
import io.jans.as.model.jwt.JwtClaims;
import org.apache.http.HttpStatus;

import static io.jans.as.model.ssa.SsaRequestParam.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;

public class SsaGetJwtAssertBuilder extends BaseAssertBuilder {

private final SsaGetJwtResponse response;
private int status;

public SsaGetJwtAssertBuilder(SsaGetJwtResponse response) {
this.response = response;
}

public SsaGetJwtAssertBuilder status(int status) {
this.status = status;
return this;
}

@Override
public void check() {
assertNotNull(response, "SsaGetJwtResponse is null");
assertEquals(response.getStatus(), status, "Unexpected HTTP status response: " + response.getStatus());
if (status == HttpStatus.SC_OK) {
assertNotNull(response.getEntity(), "The entity is null");
assertNotNull(response.getSsa(), "The ssa token is null");

Jwt jwt = Jwt.parseSilently(response.getSsa());
assertNotNull(jwt, "The jwt is null");
JwtClaims jwtClaims = jwt.getClaims();
assertNotNull(jwtClaims.getClaim(ORG_ID.getName()), "The org_id in jwt is null");
assertNotNull(jwtClaims.getClaim(SOFTWARE_ID.getName()), "The software_id in jwt is null");
assertNotNull(jwtClaims.getClaim(SOFTWARE_ROLES.getName()), "The software_roles in jwt is null");
assertNotNull(jwtClaims.getClaim(GRANT_TYPES.getName()), "The grant_types in jwt is null");

assertNotNull(jwtClaims.getClaim(JTI.getName()), "The jti in jwt is null");
assertNotNull(jwtClaims.getClaim(ISS.getName()), "The iss in jwt is null");
assertNotNull(jwtClaims.getClaim(IAT.getName()), "The iat in jwt is null");
assertNotNull(jwtClaims.getClaim(EXP.getName()), "The exp in jwt is null");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text.
*
* Copyright (c) 2020, Janssen Project
*/

package io.jans.as.client.ssa;

import io.jans.as.client.BaseTest;
import io.jans.as.client.RegisterResponse;
import io.jans.as.client.TokenResponse;
import io.jans.as.client.client.AssertBuilder;
import io.jans.as.client.ssa.create.SsaCreateResponse;
import io.jans.as.client.ssa.jwtssa.SsaGetJwtClient;
import io.jans.as.client.ssa.jwtssa.SsaGetJwtResponse;
import io.jans.as.model.common.GrantType;
import io.jans.as.model.common.ResponseType;
import io.jans.as.model.ssa.SsaScopeType;
import org.apache.http.HttpStatus;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import java.util.Collections;
import java.util.List;

public class SsaGetJwtTest extends BaseTest {

@Parameters({"redirectUris", "sectorIdentifierUri"})
@Test
public void getJwtSsaWithJtiValidResponseOkWithJwtSsa(final String redirectUris, final String sectorIdentifierUri) {
showTitle("getJwtSsaWithJtiValidResponseOkWithJwtSsa");
List<String> scopes = Collections.singletonList(SsaScopeType.SSA_ADMIN.getValue());

// Register client
RegisterResponse registerResponse = registerClient(redirectUris, Collections.singletonList(ResponseType.CODE),
Collections.singletonList(GrantType.CLIENT_CREDENTIALS), scopes, sectorIdentifierUri);
String clientId = registerResponse.getClientId();
String clientSecret = registerResponse.getClientSecret();

// Access token
TokenResponse tokenResponse = tokenClientCredentialsGrant(SsaScopeType.SSA_ADMIN.getValue(), clientId, clientSecret);
String accessToken = tokenResponse.getAccessToken();

// Create ssa
SsaCreateResponse ssaCreateResponse = createSsaWithDefaultValues(accessToken, null, null, Boolean.TRUE);
String jti = ssaCreateResponse.getJti();

// Get Jwt of SSA
SsaGetJwtClient ssaGetJwtClient = new SsaGetJwtClient(ssaEndpoint);
SsaGetJwtResponse ssaGetJwtResponse = ssaGetJwtClient.execGetJwtSsa(accessToken, jti);
showClient(ssaGetJwtClient);
AssertBuilder.ssaGetJwt(ssaGetJwtResponse).status(HttpStatus.SC_OK).check();
}

@Parameters({"redirectUris", "sectorIdentifierUri"})
@Test
public void getJwtSsaWithJtiWrongResponse422(final String redirectUris, final String sectorIdentifierUri) {
showTitle("getJwtSsaWithJtiWrongResponse422");
List<String> scopes = Collections.singletonList(SsaScopeType.SSA_ADMIN.getValue());

// Register client
RegisterResponse registerResponse = registerClient(redirectUris, Collections.singletonList(ResponseType.CODE),
Collections.singletonList(GrantType.CLIENT_CREDENTIALS), scopes, sectorIdentifierUri);
String clientId = registerResponse.getClientId();
String clientSecret = registerResponse.getClientSecret();

// Access token
TokenResponse tokenResponse = tokenClientCredentialsGrant(SsaScopeType.SSA_ADMIN.getValue(), clientId, clientSecret);
String accessToken = tokenResponse.getAccessToken();

String jti = "wrong-jti";

// Get Jwt of SSA
SsaGetJwtClient ssaGetJwtClient = new SsaGetJwtClient(ssaEndpoint);
SsaGetJwtResponse ssaGetJwtResponse = ssaGetJwtClient.execGetJwtSsa(accessToken, jti);
showClient(ssaGetJwtClient);
AssertBuilder.ssaGetJwt(ssaGetJwtResponse).status(422).check();
}

@Parameters({"redirectUris", "sectorIdentifierUri"})
@Test
public void getJwtSsaWithSsaPortalScopeResponseUnauthorized(final String redirectUris, final String sectorIdentifierUri) {
showTitle("getJwtSsaWithSsaPortalScopeResponseUnauthorized");
List<String> scopes = Collections.singletonList(SsaScopeType.SSA_ADMIN.getValue());

// Register client with scope admin
RegisterResponse registerResponse = registerClient(redirectUris, Collections.singletonList(ResponseType.CODE),
Collections.singletonList(GrantType.CLIENT_CREDENTIALS), scopes, sectorIdentifierUri);
String clientId = registerResponse.getClientId();
String clientSecret = registerResponse.getClientSecret();

// Access token
TokenResponse tokenResponse = tokenClientCredentialsGrant(SsaScopeType.SSA_ADMIN.getValue(), clientId, clientSecret);
String accessToken = tokenResponse.getAccessToken();

// Create ssa
SsaCreateResponse ssaCreateResponse = createSsaWithDefaultValues(accessToken, null, null, Boolean.TRUE);
String jti = ssaCreateResponse.getJti();

// Create a new client with scope portal
scopes = Collections.singletonList(SsaScopeType.SSA_PORTAL.getValue());
registerResponse = registerClient(redirectUris, Collections.singletonList(ResponseType.CODE),
Collections.singletonList(GrantType.CLIENT_CREDENTIALS), scopes, sectorIdentifierUri);
clientId = registerResponse.getClientId();
clientSecret = registerResponse.getClientSecret();

// Access token
tokenResponse = tokenClientCredentialsGrant(SsaScopeType.SSA_ADMIN.getValue(), clientId, clientSecret);
accessToken = tokenResponse.getAccessToken();

// Get JWT of SSA
SsaGetJwtClient ssaGetJwtClient = new SsaGetJwtClient(ssaEndpoint);
SsaGetJwtResponse ssaGetJwtResponse = ssaGetJwtClient.execGetJwtSsa(accessToken, jti);
showClient(ssaGetJwtClient);
AssertBuilder.ssaGetJwt(ssaGetJwtResponse).status(401).check();
}
}
6 changes: 6 additions & 0 deletions jans-auth-server/client/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1195,4 +1195,10 @@
<class name="io.jans.as.client.ssa.SsaRevokeTest"/>
</classes>
</test>

<test name="SSA get JWT test (HTTP)" enabled="true">
<classes>
<class name="io.jans.as.client.ssa.SsaGetJwtTest"/>
</classes>
</test>
</suite>
Loading