Skip to content

Commit

Permalink
Add ClientInstanceTokenBinding
Browse files Browse the repository at this point in the history
  • Loading branch information
VivekVinushanth committed Dec 14, 2023
1 parent f6dbb65 commit 5d916f0
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@
import static org.wso2.carbon.identity.oauth.endpoint.util.EndpointUtil.getSSOConsentService;
import static org.wso2.carbon.identity.oauth.endpoint.util.EndpointUtil.retrieveStateForErrorURL;
import static org.wso2.carbon.identity.oauth.endpoint.util.EndpointUtil.validateParams;
import static org.wso2.carbon.identity.oauth2.OAuth2Constants.TokenBinderType.CLIENT_INSTANCE;
import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.ACCESS_TOKEN_JS_OBJECT;
import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.DYNAMIC_TOKEN_DATA_FUNCTION;
import static org.wso2.carbon.identity.openidconnect.model.Constants.AUTH_TIME;
Expand Down Expand Up @@ -1732,17 +1733,19 @@ private OAuthResponse handleSuccessAuthorization(OAuthMessage oAuthMessage, OIDC
String tokenBindingValue = null;
if (tokenBinderOptional.isPresent()) {
TokenBinder tokenBinder = tokenBinderOptional.get();
tokenBindingValue = tokenBinder.getOrGenerateTokenBindingValue(oAuthMessage.getRequest());
tokenBinder.setTokenBindingValueForResponse(oAuthMessage.getResponse(), tokenBindingValue);
if (LoggerUtils.isDiagnosticLogsEnabled()) {
LoggerUtils.triggerDiagnosticLogEvent(new DiagnosticLog.DiagnosticLogBuilder(
OAuthConstants.LogConstants.OAUTH_INBOUND_SERVICE, "generate-token-binding-value")
.inputParam(LogConstants.InputKeys.CLIENT_ID, oauth2Params.getClientId())
.inputParam("token binding value", tokenBindingValue)
.configParam("token binder type", tokenBinder.getBindingType())
.resultMessage("Successfully generated token binding value.")
.logDetailLevel(DiagnosticLog.LogDetailLevel.APPLICATION)
.resultStatus(DiagnosticLog.ResultStatus.SUCCESS));
if (!tokenBinder.getBindingType().equals(CLIENT_INSTANCE)) {
tokenBindingValue = tokenBinder.getOrGenerateTokenBindingValue(oAuthMessage.getRequest());
tokenBinder.setTokenBindingValueForResponse(oAuthMessage.getResponse(), tokenBindingValue);
if (LoggerUtils.isDiagnosticLogsEnabled()) {
LoggerUtils.triggerDiagnosticLogEvent(new DiagnosticLog.DiagnosticLogBuilder(
OAuthConstants.LogConstants.OAUTH_INBOUND_SERVICE, "generate-token-binding-value")
.inputParam(LogConstants.InputKeys.CLIENT_ID, oauth2Params.getClientId())
.inputParam("token binding value", tokenBindingValue)
.configParam("token binder type", tokenBinder.getBindingType())
.resultMessage("Successfully generated token binding value.")
.logDetailLevel(DiagnosticLog.LogDetailLevel.APPLICATION)
.resultStatus(DiagnosticLog.ResultStatus.SUCCESS));
}
}
}
setAuthorizationCode(oAuthMessage, authzRespDTO, builder, tokenBindingValue, oauth2Params,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public static class TokenBinderType {
public static final String SSO_SESSION_BASED_TOKEN_BINDER = "sso-session";
public static final String COOKIE_BASED_TOKEN_BINDER = "cookie";
public static final String CERTIFICATE_BASED_TOKEN_BINDER = "certificate";
public static final String CLIENT_INSTANCE = "client-instance";

}
public static final String GROUPS = "groups";
Expand All @@ -42,6 +43,8 @@ public static class TokenBinderType {
public static final String OAUTH_CODE_PERSISTENCE_ENABLE = "OAuth.EnableAuthCodePersistence";
public static final String OAUTH_ENABLE_REVOKE_TOKEN_HEADERS = "OAuth.EnableRevokeTokenHeadersInResponse";

public static final int MAX_ALLOWED_LENGTH = 256;

/**
* Constants for global role based scope issuer.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,7 @@
import org.wso2.carbon.identity.oauth2.scopeservice.ScopeMetadataService;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinder;
import org.wso2.carbon.identity.oauth2.token.bindings.handlers.TokenBindingExpiryEventHandler;
import org.wso2.carbon.identity.oauth2.token.bindings.impl.CertificateBasedTokenBinder;
import org.wso2.carbon.identity.oauth2.token.bindings.impl.CookieBasedTokenBinder;
import org.wso2.carbon.identity.oauth2.token.bindings.impl.DeviceFlowTokenBinder;
import org.wso2.carbon.identity.oauth2.token.bindings.impl.SSOSessionBasedTokenBinder;
import org.wso2.carbon.identity.oauth2.token.bindings.impl.*;
import org.wso2.carbon.identity.oauth2.token.handlers.claims.JWTAccessTokenClaimProvider;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.oauth2.validators.scope.RoleBasedScopeIssuer;
Expand Down Expand Up @@ -267,6 +264,10 @@ protected void activate(ComponentContext context) {
bundleContext.registerService(TokenBinderInfo.class.getName(), certificateBasedTokenBinder, null);
}

// Client instance based access token binder.
ClientInstanceTokenBinder clientInstanceTokenBinder = new ClientInstanceTokenBinder();
bundleContext.registerService(TokenBinderInfo.class.getName(), clientInstanceTokenBinder, null);

bundleContext.registerService(ResponseTypeRequestValidator.class.getName(),
new DeviceFlowResponseTypeRequestValidator(), null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.wso2.carbon.identity.oauth.common.OAuthConstants.GrantTypes.REFRESH_TOKEN;
import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OauthAppStates.APP_STATE_ACTIVE;
import static org.wso2.carbon.identity.oauth2.OAuth2Constants.MAX_ALLOWED_LENGTH;
import static org.wso2.carbon.identity.oauth2.Oauth2ScopeConstants.CONSOLE_SCOPE_PREFIX;
import static org.wso2.carbon.identity.oauth2.Oauth2ScopeConstants.INTERNAL_SCOPE_PREFIX;
import static org.wso2.carbon.identity.oauth2.Oauth2ScopeConstants.SYSTEM_SCOPE;
Expand Down Expand Up @@ -1065,11 +1066,22 @@ private void handleTokenBinding(OAuth2AccessTokenReqDTO tokenReqDTO, String gran
throw new IdentityOAuth2ClientException(OAuth2ErrorCodes.INVALID_REQUEST,
"TLS certificate not found in the request.");
}
if (OAuth2Constants.TokenBinderType.CLIENT_INSTANCE.equals(tokenBinder.getBindingType())) {
// Treat as 'None' token binding requests.
tokReqMsgCtx.setTokenBinding(null);
return;
}
throw new IdentityOAuth2Exception(
"Token binding reference cannot be retrieved form the token binder: " + tokenBinder
.getBindingType());
}

if (OAuth2Constants.TokenBinderType.CLIENT_INSTANCE.equals(tokenBinder.getBindingType()) &&
tokenBindingValueOptional.get().length() >= MAX_ALLOWED_LENGTH) {
throw new IdentityOAuth2ClientException(OAuth2ErrorCodes.INVALID_REQUEST,
"Token binding reference length exceeds limit for the token binder: " + tokenBinder.getBindingType());
}

String tokenBindingValue = tokenBindingValueOptional.get();
tokReqMsgCtx.setTokenBinding(
new TokenBinding(tokenBinder.getBindingType(), OAuth2Util.getTokenBindingReference(tokenBindingValue),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com).
*
* WSO2 Inc. licenses this file to you 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.wso2.carbon.identity.oauth2.token.bindings.impl;

import org.apache.commons.lang.StringUtils;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.model.RequestParameter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

import static org.wso2.carbon.identity.oauth.common.OAuthConstants.GrantTypes.AUTHORIZATION_CODE;
import static org.wso2.carbon.identity.oauth.common.OAuthConstants.GrantTypes.PASSWORD;
import static org.wso2.carbon.identity.oauth2.OAuth2Constants.TokenBinderType.CLIENT_INSTANCE;


/**
* Client Instance Reference binding to the token.
*/
public class ClientInstanceTokenBinder extends AbstractTokenBinder {

private static final String CLIENT_INSTANCE_REF = "clientInstanceRef";

@Override
public Optional<String> getTokenBindingValue(OAuth2AccessTokenReqDTO oAuth2AccessTokenReqDTO) {

RequestParameter[] parameters = oAuth2AccessTokenReqDTO.getRequestParameters();
for (RequestParameter parameter : parameters) {
if (CLIENT_INSTANCE_REF.equals(parameter.getKey())
&& StringUtils.isNotBlank(parameter.getValue()[0])) {
return Optional.ofNullable(parameter.getValue()[0]);
}
}
return Optional.empty();
}

@Override
public String getDisplayName() {

return "Client Instance";
}

@Override
public String getDescription() {

return "Client Instance Token Binding";
}

@Override
public String getBindingType() {

return CLIENT_INSTANCE;
}

@Override
public List<String> getSupportedGrantTypes() {
Set<String> supportedGrantTypes = OAuthServerConfiguration.getInstance().getSupportedGrantTypes().keySet();
return supportedGrantTypes.stream().collect(Collectors.toList());
}

@Override
public String getOrGenerateTokenBindingValue(HttpServletRequest request) {

return null;
}

@Override
public void setTokenBindingValueForResponse(HttpServletResponse response, String bindingValue) {

}

@Override
public void clearTokenBindingElements(HttpServletRequest request, HttpServletResponse response) {

}

@Override
public boolean isValidTokenBinding(Object request, String bindingReference) {

/*
* As the token binding reference is same as the device code, the token call implementation
* will validate the device code. So no need to revalidate here.
*/
return true;
}

@Override
public boolean isValidTokenBinding(OAuth2AccessTokenReqDTO oAuth2AccessTokenReqDTO, String bindingReference) {

/*
* As the token binding reference is same as the device code, the token call implementation
* will validate the device code. So no need to revalidate here.
*/
return true;
}
}

0 comments on commit 5d916f0

Please sign in to comment.