/* * Copyright (c) Smals */ package be.smals.dimona.webservice.rest.tokengenerator; import java.io.InputStream; import java.net.URI; import java.security.KeyStore; import java.security.PrivateKey; import java.security.SecureRandom; import java.util.Arrays; import java.util.Date; import java.util.Map; import javax.json.JsonObject; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import org.apache.commons.collections4.map.HashedMap; import org.glassfish.jersey.filter.LoggingFilter; import org.junit.BeforeClass; import org.junit.Test; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSHeader; import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import com.nimbusds.oauth2.sdk.AccessTokenResponse; import com.nimbusds.oauth2.sdk.ClientCredentialsGrant; import com.nimbusds.oauth2.sdk.Scope; import com.nimbusds.oauth2.sdk.TokenErrorResponse; import com.nimbusds.oauth2.sdk.TokenRequest; import com.nimbusds.oauth2.sdk.TokenResponse; import com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT; /** * Example to invoke a protected resource with OAuth2 access token (client credentials flow) *

* AccessToken request used RFC 7523 * * @author wisa */ public class ClientCredentialTokenGenerator { private static final String AUDIENCE = "https://services.socialsecurity.be/REST/oauth/v5/token"; private static final String CLIENT_ID = "self-service:expeditor:624"; private static final String SCOPE_1 = "scope:dimona:declaration:consult"; private static final String SCOPE_2 = "scope:dimona:declaration:declarant"; private static final String OAUTH_SERVER_URL = "https://services.socialsecurity.be/REST/oauth/v5/token"; private final static String RESOURCE_SERVER = "https://services.socialsecurity.be/REST/dimona/v1"; private static final String JKS_FILE = "/expeditor_624.jks"; private static final char[] JKS_PASSWORD = "PASSWORD".toCharArray(); private static final String ALIAS_NAME = "self-service:expeditor:624"; private static final char[] ALIAS_PASSWORD = JKS_PASSWORD; private static PrivateKey privateKey; @BeforeClass public static void init() throws Exception { KeyStore keyStore = KeyStore.getInstance("JKS"); InputStream stream = ClientCredentialTokenGenerator.class.getResourceAsStream(JKS_FILE); keyStore.load(stream, JKS_PASSWORD); privateKey = (PrivateKey) keyStore.getKey(ALIAS_NAME, ALIAS_PASSWORD); } @Test public void testClientCredentialFlow() throws Exception { String authorizationHeader = getAuthorizationHeader(SCOPE_1, SCOPE_2); Client client = ClientBuilder.newClient().register(new LoggingFilter()); JsonObject response = client// .target(RESOURCE_SERVER)// .path("/ping/secure")// .request() .header("Authorization", authorizationHeader)// .get(JsonObject.class); } private String getAuthorizationHeader(String... scopes) throws Exception { JWSHeader jwtJwsHeader = new JWSHeader(JWSAlgorithm.RS256); JWTClaimsSet jwtClaimsSet = new JWTClaimsSet.Builder() .audience(AUDIENCE) .jwtID(getSecureID()) .issuer(CLIENT_ID) .issueTime(new Date(System.currentTimeMillis())) .expirationTime(new Date(System.currentTimeMillis() + 5000L)) .subject(CLIENT_ID) .build(); SignedJWT jwt = new SignedJWT(jwtJwsHeader, jwtClaimsSet); jwt.sign(new RSASSASigner(privateKey)); System.out.println("Token for authentication :" + jwt.serialize()); // NOT standard . Will be optional with release 2018/1 of OAUTH socsec. Map customParam = new HashedMap(); customParam.put("client_id", CLIENT_ID); TokenRequest request = new TokenRequest( new URI(OAUTH_SERVER_URL),// new PrivateKeyJWT(jwt), //JWT signed with RSA Key new ClientCredentialsGrant(),// new Scope(scopes),// customParam); // NOT standard . Will be optional with release 2018/1 of OAUTH socsec. TokenResponse response = TokenResponse.parse(request.toHTTPRequest().send()); if (response.indicatesSuccess()) { AccessTokenResponse successResponse = (AccessTokenResponse) response; return successResponse.getTokens().getBearerAccessToken().toAuthorizationHeader(); } else { // We got an error response... TokenErrorResponse errorResponse = (TokenErrorResponse) response; System.out.println(String.format("Fail with httpCode \"%s\" and error_description \"%s\"", errorResponse.getErrorObject().getHTTPStatusCode(), errorResponse.getErrorObject().getDescription())); throw new RuntimeException("Access token request failed"); } } private String getSecureID() { SecureRandom random = new SecureRandom(); byte bytes[] = new byte[20]; random.nextBytes(bytes); return Arrays.toString(bytes); } }