How to add new claims to ID token by implementing Supplementary OSGi service in WSO2 Identity Server ?
I have implemented a OSGi service to add new claims to ID token in OpenID Connect protocol in Identity Server. According to the current implementation, there is no any way to insert claims into ID Token from outside.This ClaimProvider OSGi service can be plugged in. If we want to add claims into ID Token in our own way, rather than changing the existing code base, this service can be used. So this service can be plugged in and can be used to inject claims into ID Token.
What is this ClaimProvider interface ?
ClaimAdder interface has two methods. So anyone can implement this interface and publish their service.
The ClaimProvider interface is shown below.
public interface ClaimProvider {/**
* @param authAuthzReqMessageContext
* @param authorizeRespDTO
* @return map of id token claims
* @throws IdentityOAuth2Exception
*/
Map<String, Object> getAdditionalClaims(OAuthAuthzReqMessageContext authAuthzReqMessageContext,
OAuth2AuthorizeRespDTO authorizeRespDTO)
throws IdentityOAuth2Exception;/**
* @param tokenReqMessageContext
* @param tokenRespDTO
* @return map of id token claims
* @throws IdentityOAuth2Exception
*/
Map<String, Object> getAdditionalClaims(OAuthTokenReqMessageContext tokenReqMessageContext,
OAuth2AccessTokenRespDTO tokenRespDTO)
throws IdentityOAuth2Exception;
}
First methods can be used when the ID Token request comes from Authorize endpoint and second method can be used when ID Token request comes from token endpoint.
How to add new claims to ID Token?
1. Add the dependency and import packages in the pom file
First you need to add dependency in your pom file.
<dependency>
<groupId>org.wso2.carbon.identity.inbound.auth.oauth2</groupId>
<artifactId>org.wso2.carbon.identity.oauth</artifactId>
<version>${identity.inbound.auth.oauth.version}</version>
</dependency><Import-Package>
org.wso2.carbon.identity.oauth2.authz;version="${identity.inbound.auth.oauth.imp.pkg.version.range}",
org.wso2.carbon.identity.oauth2.dto;version="${identity.inbound.auth.oauth.imp.pkg.version.range}",
org.wso2.carbon.identity.oauth2.token;version="${identity.inbound.auth.oauth.imp.pkg.version.range}",
org.wso2.carbon.identity.openidconnect.*;version="${identity.inbound.auth.oauth.imp.pkg.version.range}",
</<Import-Package><properties>
<identity.inbound.auth.oauth.version>5.5.124-SNAPSHOT</identity.inbound.auth.oauth.version>
<identity.inbound.auth.oauth.imp.pkg.version.range>[5.0.0, 6.0.0)</identity.inbound.auth.oauth.imp.pkg.version.range>
</properties>
2. Implement the service interface
Then you can implement ClaimProvider service and, inject new claims to ID token in Identity Server. This is a convenient way to insert new claims without doing any change in the code base of DefaultIDTokenBuilder.
You need to simply return a Map which has claim name and value pair.
A sample implementation of ClaimProvider interface is shown below.
public class ClaimProviderImpl implements ClaimProvider {
@Override
public Map<String, Object> getAdditionalClaims(OAuthAuthzReqMessageContext oAuthAuthzReqMessageContext,
OAuth2AuthorizeRespDTO oAuth2AuthorizeRespDTO)
throws IdentityOAuth2Exception {
Map<String, Object> addtionalClaims = new HashMap<>();
this.name = "sid";
this.claimValue="123-4rt5-678ui";
addtionalClaims.put(name, claimValue);
return addtionalClaims;
}
@Override
public Map<String, Object> getAdditionalClaims(OAuthTokenReqMessageContext oAuthTokenReqMessageContext,
OAuth2AccessTokenRespDTO oAuth2AccessTokenRespDTO)
throws IdentityOAuth2Exception {
Map<String, Object> addtionalClaims = new HashMap<>();
this.name = "sid";
this.claimValue="123-4rt5-678ui";
addtionalClaims.put(name, claimValue);
return addtionalClaims;}
3. Publish your service.
After implemeting the ClaimProvider service, you need to publish the service. Then only OAuth component in IS can find your service and consume it. To publish your service, You can use a Service component.
@Component(
name = "identity.oidc.session.component",
immediate = true
)
public class OIDCSessionManagementComponent { private static final Log log = LogFactory.getLog(OIDCSessionManagementComponent.class);protected void activate(ComponentContext context) {
ClaimProviderImpl claimProviderImpl = new ClaimProviderImpl();
try {
context.getBundleContext().registerService(ClaimProvider.class.getName(), claimProviderImpl, null);
} catch (Exception e) {
String msg = "Error when registering ClaimProvider service";
log.error(msg, e);
throw new RuntimeException(msg, e);
}if (log.isDebugEnabled()) {
log.debug("ClaimProvider bundle is activated");
}
}
}
Now you have published your service!
org.wso2.carbon.identity.oauth component in identity-inbound-oauth is listening to ClaimProvider services. Once you registered your service, that can be found by the Default IDTokenBuilder class. So that your claims will be added to ID token.
For example, In OpenIDConnect Back-channel logout, sid claim needs to be inserted into ID Token. So in that case, if we don’t have this service, we needs to change the existing code base. Now , by using this service, without changing the existing code, we insert sid claim into ID Token.
Similarly there can be so many instance where there can be a need to inject new claims for some specific purposes. In that situations, this OSGi service can be useful!