Skip to content

Commit

Permalink
Support for OAuth2 Snyk provider
Browse files Browse the repository at this point in the history
  • Loading branch information
sberyozkin committed Nov 30, 2024
1 parent 70e6965 commit 55adb7f
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
@Priority(Priorities.AUTHENTICATION)
public class AccessTokenRequestReactiveFilter implements ResteasyReactiveClientRequestFilter {
private static final Logger LOG = Logger.getLogger(AccessTokenRequestReactiveFilter.class);
private static final String BEARER_SCHEME_WITH_SPACE = "Bearer ";
private static final String BEARER_SCHEME = "Bearer";
private static final String ERROR_MSG = "OIDC Token Propagation Reactive requires a safe (isolated) Vert.x sub-context because configuration property 'quarkus.rest-client-oidc-token-propagation.enabled-during-authentication' has been set to true, but the current context hasn't been flagged as such.";
private final boolean enabledDuringAuthentication;
private final Instance<TokenCredential> accessToken;
Expand Down Expand Up @@ -118,13 +118,17 @@ protected String getClientName() {

public void propagateToken(ResteasyReactiveClientRequestContext requestContext, String accessToken) {
if (accessToken != null) {
requestContext.getHeaders().putSingle(HttpHeaders.AUTHORIZATION, BEARER_SCHEME_WITH_SPACE + accessToken);
requestContext.getHeaders().putSingle(HttpHeaders.AUTHORIZATION, getAuthorizationScheme() + " " + accessToken);
} else {
LOG.debugf("Access token is null, aborting the request with HTTP 401 error");
abortRequest(requestContext);
}
}

protected String getAuthorizationScheme() {
return BEARER_SCHEME;
}

protected boolean verifyTokenInstance(ResteasyReactiveClientRequestContext requestContext) {
if (enabledDuringAuthentication) {
// TokenCredential cannot be accessed from CDI during authentication process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,11 @@ public enum ResponseMode {
*/
public Optional<Boolean> userInfoRequired = Optional.empty();

/**
* Authorization scheme for requesting UserInfo.
*/
public String userInfoScheme = OidcConstants.BEARER_SCHEME;

/**
* Session age extension in minutes.
* The user session age property is set to the value of the ID token life-span by default and
Expand Down Expand Up @@ -2032,6 +2037,7 @@ public static enum Provider {
MASTODON,
MICROSOFT,
SLACK,
SNYK,
SPOTIFY,
STRAVA,
TWITCH,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ public Uni<UserInfoResponse> apply(Throwable t) {
}

private Uni<UserInfoResponse> doGetUserInfo(OidcRequestContextProperties requestProps, String token, List<String> cookies) {
LOG.debugf("Get UserInfo on: %s auth: %s", metadata.getUserInfoUri(), OidcConstants.BEARER_SCHEME + " " + token);
LOG.debugf("Get UserInfo on: %s auth: %s", metadata.getUserInfoUri(),
oidcConfig.authentication.userInfoScheme + " " + token);

HttpRequest<Buffer> request = client.getAbs(metadata.getUserInfoUri());
if (!cookies.isEmpty()) {
Expand All @@ -142,7 +143,7 @@ private Uni<UserInfoResponse> doGetUserInfo(OidcRequestContextProperties request
return OidcCommonUtils
.sendRequest(vertx,
filterHttpRequest(requestProps, OidcEndpoint.Type.USERINFO, request, null)
.putHeader(AUTHORIZATION_HEADER, OidcConstants.BEARER_SCHEME + " " + token),
.putHeader(AUTHORIZATION_HEADER, oidcConfig.authentication.userInfoScheme + " " + token),
oidcConfig.useBlockingDnsLookup)
.onItem().transform(resp -> getUserInfo(requestProps, resp));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,12 @@ enum ResponseMode {
@ConfigDocDefault("true when UserInfo bean is injected, false otherwise")
Optional<Boolean> userInfoRequired();

/**
* Authorization scheme for requesting UserInfo.
*/
@WithDefault(OidcConstants.BEARER_SCHEME)
String userInfoScheme();

/**
* Session age extension in minutes.
* The user session age property is set to the value of the ID token life-span by default and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static OidcTenantConfig provider(OidcTenantConfig.Provider provider) {
case MASTODON -> mastodon();
case MICROSOFT -> microsoft();
case SLACK -> slack();
case SNYK -> snyk();
case SPOTIFY -> spotify();
case STRAVA -> strava();
case TWITCH -> twitch();
Expand Down Expand Up @@ -215,4 +216,19 @@ private static OidcTenantConfig discord() {

return ret;
}

private static OidcTenantConfig snyk() {
OidcTenantConfig ret = new OidcTenantConfig();
ret.setAuthServerUrl("https://app.snyk.io/oauth2");
ret.setApplicationType(OidcTenantConfig.ApplicationType.WEB_APP);
ret.setDiscoveryEnabled(false);
ret.setAuthorizationPath("authorize");
ret.setTokenPath("token");
ret.getAuthentication().setScopes(List.of("org.read"));
ret.getAuthentication().setIdTokenRequired(false);
ret.getAuthentication().userInfoScheme = "token";
ret.getToken().setVerifyAccessTokenWithUserInfo(true);
ret.setUserInfoPath("https://api.snyk.io/rest/self");
return ret;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Optional;
import java.util.OptionalInt;

import io.quarkus.oidc.common.runtime.OidcConstants;
import io.quarkus.runtime.configuration.TrimmedStringConverter;
import io.smallrye.config.WithConverter;

Expand Down Expand Up @@ -143,6 +144,7 @@ enum ConfigMappingMethods {
AUTHENTICATION_ALLOW_MULTIPLE_CODE_FLOWS,
AUTHENTICATION_FAIL_ON_MISSING_STATE_PARAM,
AUTHENTICATION_USER_INFO_REQUIRED,
AUTHENTICATION_USER_INFO_SCHEME,
AUTHENTICATION_SESSION_AGE_EXTENSION,
AUTHENTICATION_STATE_COOKIE_AGE,
AUTHENTICATION_JAVASCRIPT_AUTO_REDIRECT,
Expand Down Expand Up @@ -691,6 +693,12 @@ public boolean failOnMissingStateParam() {
return false;
}

@Override
public String userInfoScheme() {
invocationsRecorder.put(ConfigMappingMethods.AUTHENTICATION_USER_INFO_SCHEME, true);
return OidcConstants.BEARER_SCHEME;
}

@Override
public Optional<Boolean> userInfoRequired() {
invocationsRecorder.put(ConfigMappingMethods.AUTHENTICATION_USER_INFO_REQUIRED, true);
Expand Down

0 comments on commit 55adb7f

Please sign in to comment.