Skip to content
Open
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
Expand Up @@ -17,15 +17,24 @@

import static io.serverlessworkflow.api.types.OAuth2AuthenticationDataClient.ClientAuthentication.CLIENT_SECRET_POST;
import static io.serverlessworkflow.impl.WorkflowUtils.isValid;
import static io.serverlessworkflow.impl.auth.AuthUtils.ACTOR;
import static io.serverlessworkflow.impl.auth.AuthUtils.ACTOR_TOKEN;
import static io.serverlessworkflow.impl.auth.AuthUtils.ACTOR_TOKEN_TYPE;
import static io.serverlessworkflow.impl.auth.AuthUtils.AUDIENCES;
import static io.serverlessworkflow.impl.auth.AuthUtils.AUTHENTICATION;
import static io.serverlessworkflow.impl.auth.AuthUtils.CLIENT;
import static io.serverlessworkflow.impl.auth.AuthUtils.ENCODING;
import static io.serverlessworkflow.impl.auth.AuthUtils.REQUEST;
import static io.serverlessworkflow.impl.auth.AuthUtils.SCOPES;
import static io.serverlessworkflow.impl.auth.AuthUtils.SUBJECT;
import static io.serverlessworkflow.impl.auth.AuthUtils.SUBJECT_TOKEN;
import static io.serverlessworkflow.impl.auth.AuthUtils.SUBJECT_TOKEN_TYPE;
import static io.serverlessworkflow.impl.auth.AuthUtils.TOKEN;
import static io.serverlessworkflow.impl.auth.AuthUtils.TYPE;

import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
import io.serverlessworkflow.api.types.OAuth2AuthenticationDataClient;
import io.serverlessworkflow.api.types.OAuth2TokenDefinition;
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowUtils;
import java.util.Arrays;
Expand All @@ -51,6 +60,7 @@ public HttpRequestInfo apply(T authenticationData) {
audience(authenticationData);
scope(authenticationData);
authenticationMethod(authenticationData);
subjectActor(authenticationData);
return requestBuilder.build();
}

Expand All @@ -61,6 +71,7 @@ public HttpRequestInfo apply(Map<String, Object> secret) {
audience(secret);
scope(secret);
authenticationMethod(secret);
subjectActor(secret);
return requestBuilder.build();
}

Expand All @@ -80,44 +91,66 @@ protected void audience(Map<String, Object> secret) {
}

protected void authenticationMethod(T authenticationData) {
ClientSecretHandler secretHandler;
switch (getClientAuthentication(authenticationData)) {
case CLIENT_SECRET_BASIC:
secretHandler = new ClientSecretBasic(application, requestBuilder);
case CLIENT_SECRET_JWT:
throw new UnsupportedOperationException("Client Secret JWT is not supported yet");
case PRIVATE_KEY_JWT:
throw new UnsupportedOperationException("Private Key JWT is not supported yet");
default:
secretHandler = new ClientSecretPost(application, requestBuilder);
}
ClientSecretHandler secretHandler =
switch (getClientAuthentication(authenticationData)) {
case CLIENT_SECRET_BASIC -> new ClientSecretBasic(application, requestBuilder);
case CLIENT_SECRET_JWT, PRIVATE_KEY_JWT ->
new JwtClientAssertion(application, requestBuilder);
default -> new ClientSecretPost(application, requestBuilder);
};
secretHandler.accept(authenticationData);
}

@SuppressWarnings("unchecked")
protected void authenticationMethod(Map<String, Object> secret) {
Map<String, Object> client = (Map<String, Object>) secret.get(CLIENT);
ClientSecretHandler secretHandler;
String auth = (String) client.get(AUTHENTICATION);
if (auth == null) {
secretHandler = new ClientSecretPost(application, requestBuilder);
} else {
switch (auth) {
case "client_secret_basic":
secretHandler = new ClientSecretBasic(application, requestBuilder);
break;
default:
case "client_secret_post":
secretHandler = new ClientSecretPost(application, requestBuilder);
break;
case "private_key_jwt":
throw new UnsupportedOperationException("Private Key JWT is not supported yet");
case "client_secret_jwt":
throw new UnsupportedOperationException("Client Secret JWT is not supported yet");
}
secretHandler =
switch (auth) {
case "client_secret_basic" -> new ClientSecretBasic(application, requestBuilder);
case "private_key_jwt", "client_secret_jwt" ->
new JwtClientAssertion(application, requestBuilder);
default -> new ClientSecretPost(application, requestBuilder);
};
}
secretHandler.accept(secret);
}

protected void subjectActor(T authenticationData) {
tokenParam(SUBJECT_TOKEN, SUBJECT_TOKEN_TYPE, authenticationData.getSubject());
tokenParam(ACTOR_TOKEN, ACTOR_TOKEN_TYPE, authenticationData.getActor());
}

private void tokenParam(String tokenKey, String typeKey, OAuth2TokenDefinition definition) {
if (definition != null) {
requestBuilder
.addQueryParam(
tokenKey, WorkflowUtils.buildStringFilter(application, definition.getToken()))
.addQueryParam(
typeKey, WorkflowUtils.buildStringFilter(application, definition.getType()));
}
}
Comment thread
fjtirado marked this conversation as resolved.

protected void subjectActor(Map<String, Object> secret) {
tokenParam(SUBJECT_TOKEN, SUBJECT_TOKEN_TYPE, secret.get(SUBJECT));
tokenParam(ACTOR_TOKEN, ACTOR_TOKEN_TYPE, secret.get(ACTOR));
}

private void tokenParam(String tokenKey, String typeKey, Object rawDefinition) {
if (rawDefinition instanceof Map<?, ?> definition) {
requestBuilder
.addQueryParam(
tokenKey,
WorkflowUtils.buildStringFilter(application, (String) definition.get(TOKEN)))
.addQueryParam(
typeKey, WorkflowUtils.buildStringFilter(application, (String) definition.get(TYPE)));
}
}
Comment thread
fjtirado marked this conversation as resolved.

private OAuth2AuthenticationDataClient.ClientAuthentication getClientAuthentication(
OAuth2AuthenticationData authenticationData) {
return authenticationData.getClient() == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@ private AuthUtils() {}
public static final String REQUEST = "request";
public static final String ENCODING = "encoding";
public static final String AUTHENTICATION = "authentication";
public static final String ASSERTION = "assertion";
public static final String SUBJECT = "subject";
public static final String ACTOR = "actor";
public static final String TYPE = "type";
public static final String REVOCATION = "revocation";
public static final String INTROSPECTION = "introspection";

public static final String CLIENT_ID = "client_id";
public static final String CLIENT_ASSERTION = "client_assertion";
public static final String CLIENT_ASSERTION_TYPE = "client_assertion_type";
public static final String JWT_BEARER_ASSERTION_TYPE =
"urn:ietf:params:oauth:client-assertion-type:jwt-bearer";

public static final String SUBJECT_TOKEN = "subject_token";
public static final String SUBJECT_TOKEN_TYPE = "subject_token_type";
public static final String ACTOR_TOKEN = "actor_token";
public static final String ACTOR_TOKEN_TYPE = "actor_token_type";

private static final String AUTH_HEADER_FORMAT = "%s %s";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import static io.serverlessworkflow.api.types.OAuth2AuthenticationData.OAuth2AuthenticationDataGrant.CLIENT_CREDENTIALS;
import static io.serverlessworkflow.api.types.OAuth2AuthenticationData.OAuth2AuthenticationDataGrant.PASSWORD;
import static io.serverlessworkflow.api.types.OAuth2AuthenticationData.OAuth2AuthenticationDataGrant.URN_IETF_PARAMS_OAUTH_GRANT_TYPE_TOKEN_EXCHANGE;

import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
import io.serverlessworkflow.impl.WorkflowApplication;
Expand Down Expand Up @@ -48,7 +49,8 @@ void accept(OAuth2AuthenticationData authenticationData) {
}

password(authenticationData);
} else if (authenticationData.getGrant().equals(CLIENT_CREDENTIALS)) {
} else if (authenticationData.getGrant().equals(CLIENT_CREDENTIALS)
|| authenticationData.getGrant().equals(URN_IETF_PARAMS_OAUTH_GRANT_TYPE_TOKEN_EXCHANGE)) {
if (authenticationData.getClient() == null
|| authenticationData.getClient().getId() == null
|| authenticationData.getClient().getSecret() == null) {
Expand All @@ -74,6 +76,7 @@ void accept(Map<String, Object> secret) {
String grant = Objects.requireNonNull((String) secret.get("grant"), "Grant is mandatory field");
switch (grant) {
case "client_credentials":
case "urn:ietf:params:oauth:grant-type:token-exchange":
clientCredentials(secret);
break;
case "password":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ protected ClientSecretPost(
protected void clientCredentials(OAuth2AuthenticationData authenticationData) {
requestBuilder
.withGrantType(authenticationData.getGrant().value())
.addQueryParam(
.addClientAuthParam(
"client_id",
WorkflowUtils.buildStringFilter(application, authenticationData.getClient().getId()))
.addQueryParam(
.addClientAuthParam(
"client_secret",
WorkflowUtils.buildStringFilter(
application, authenticationData.getClient().getSecret()));
Expand All @@ -64,8 +64,8 @@ protected void clientCredentials(Map<String, Object> secret) {
Map<String, Object> client = (Map<String, Object>) secret.get(CLIENT);
requestBuilder
.withGrantType((String) secret.get(GRANT))
.addQueryParam("client_id", (String) client.get(ID))
.addQueryParam("client_secret", (String) client.get(SECRET));
.addClientAuthParam("client_id", (String) client.get(ID))
.addClientAuthParam("client_secret", (String) client.get(SECRET));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
import io.serverlessworkflow.impl.WorkflowValueResolver;
import java.net.URI;
import java.util.Map;
import java.util.Optional;

public record HttpRequestInfo(
Map<String, WorkflowValueResolver<String>> headers,
Map<String, WorkflowValueResolver<String>> queryParams,
Map<String, WorkflowValueResolver<String>> clientAuthParams,
WorkflowValueResolver<URI> uri,
Optional<WorkflowValueResolver<URI>> revocationUri,
Optional<WorkflowValueResolver<URI>> introspectionUri,
String grantType,
String contentType) {}
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,30 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

class HttpRequestInfoBuilder {

private Map<String, WorkflowValueResolver<String>> headers;

private Map<String, WorkflowValueResolver<String>> queryParams;

private Map<String, WorkflowValueResolver<String>> clientAuthParams;

private WorkflowValueResolver<URI> uri;

private Optional<WorkflowValueResolver<URI>> revocationUri = Optional.empty();

private Optional<WorkflowValueResolver<URI>> introspectionUri = Optional.empty();

private String grantType;

private String contentType;

HttpRequestInfoBuilder() {
headers = new HashMap<>();
queryParams = new HashMap<>();
clientAuthParams = new HashMap<>();
}

HttpRequestInfoBuilder addHeader(String key, String token) {
Expand All @@ -61,11 +69,32 @@ HttpRequestInfoBuilder addQueryParam(String key, WorkflowValueResolver<String> t
return this;
}

HttpRequestInfoBuilder addClientAuthParam(String key, String token) {
clientAuthParams.put(key, (w, t, m) -> token);
return this;
}

HttpRequestInfoBuilder addClientAuthParam(String key, WorkflowValueResolver<String> token) {
clientAuthParams.put(key, token);
return this;
}

HttpRequestInfoBuilder withUri(WorkflowValueResolver<URI> uri) {
this.uri = uri;
return this;
}

HttpRequestInfoBuilder withRevocationUri(Optional<WorkflowValueResolver<URI>> revocationUri) {
this.revocationUri = revocationUri;
return this;
}

HttpRequestInfoBuilder withIntrospectionUri(
Optional<WorkflowValueResolver<URI>> introspectionUri) {
this.introspectionUri = introspectionUri;
return this;
}

HttpRequestInfoBuilder withContentType(OAuth2TokenRequest oAuth2TokenRequest) {
if (oAuth2TokenRequest != null) {
this.contentType = oAuth2TokenRequest.getEncoding().value();
Expand All @@ -91,6 +120,14 @@ HttpRequestInfo build() {
if (contentType == null) {
contentType = APPLICATION_X_WWW_FORM_URLENCODED.value();
}
return new HttpRequestInfo(headers, queryParams, uri, grantType, contentType);
return new HttpRequestInfo(
headers,
queryParams,
clientAuthParams,
uri,
revocationUri,
introspectionUri,
grantType,
contentType);
}
}
Loading
Loading