I started to use Spring OAuth2 and in the process, I struggled to find relevant tutorials and content mostly because of the following
I did not want to use Spring Boot
I did not want to use Java configs rather xml configuration
I needed to customize Spring OAuth2 grant flows and other features for our specific needs
I needed to disable some grant flows
I needed to Spring OAuth2 to use custom Users and Roles
I needed to use store oauth_client details in a custom database tab
Other stuff
I have managed to write my implementation that addresses the above points and now I want to share my findings in order to save others the suffering.
See my answer for the approach I followed and feel free to share your advise, suggestions and feedback if you have any.
The main objective of this question is to
Get feedback, suggestions and advise about approach I followed
Share all that I learned the hard way with the hope of saving others the trouble and giving back to the community what I learned from community.
I started off with basic setup of Spring Security framework using mainly XML configuration.
Spring Security OAuth2
I did a ton of google searches and looked at a bunch of repositories including the main Spring OAuth 2 repo.
I started off with OAuth2 XML Configs and I needed to make changes in order to
Organize, clean up the spring-security.xml OAuth2 config file
Instruct Spring OAuth2 to lookup a different (customized) user and role tables from database
Instruct Spring OAuth2 to lookup a different (customized) oauth_client_details table (with extra columns)
Use JWT Tokens and make required changes to customize the JWT Token to include custom claims
Develop custom implementation of OAuth2RequestValidator and inject it to the Token endpoint using XML configuration
Disable a grant flow
Enable verify token endpiont /oauth/check_token and validate JWT token custom claims
And, I have achieved the above as follow
1. Organize and clean up spring-security.xml
The default spring-security.xml linked above comes with the following assumptions
Both Authorization server and Resource server are in the same machine.
Use in-memory users
Use in-memory oauth clients
I would like to keep the Authentication and Resource server separate hence, I stripped off all the protected endpoints configs and the in-memory user-service and oauth-client-details.
2. Instruct OAuth2 to lookup different user and roles database table
To achieve this, I made sure that
MyUser object implements the following org.springframework.security.core.userdetails.UserDetails
and overrides the getAuthorities which return a collection of GrantedAuthority
MyRole object implements the org.springframework.security.core.GrantedAuthorityand override the method getAuthority
I now need to inform the Spring OAuth2 about the above customised MyUser and MyRole and in order to do that, I needed to do the following
Provide custom implementation for org.springframework.security.core.userdetails.UserDetailsService interface and override the inherited loadByUsername method to query my custom user database table and retrieve the user with its roles and construct an instance of org.springframework.security.core.userdetails.User and return it.
Create a <bean> of the above custom implementation and let's call it MyUserDetailsService and place it in spring-security.xml config file. Something as follow
<bean id="myUserDetailsService" class="your.package.hierarcy.goes.here.MyUserDetailsService" />
Just defining a bean is once again not enough, we have to tell Spring OAuth2 to use the MyUserDetailsService and to do that we need to inject the myUserDetailsService into Spring OAuth2's default authentication provider or our own authentication provider that will then get passed to authentication-manager element, as shown below
<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="myUserDetailsService"/>
<!-- if you encode or encrypt your password, then pass encoder-->
<!--<property name="passwordEncoder" ref="passwordEncoder"/>-->
</bean>
Finally we need to inject the above Authentication Provider into the Authentication Manager specified in spring-security.xml as shown below
<!-- Original -->
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service id="userDetailsService">
<user name="marissa" password="koala" authorities="ROLE_USER" />
<user name="paul" password="emu" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
Change the above with below
<!-- Modified with our own implementation of UserDetailsService -->
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="daoAuthenticationProvider" />
</authentication-manager>
And now to use the above Authentication Manager which uses, pass it to a grant flow in the <oauth:authorization-server> as follow
<oauth:password authentication-manager-ref="authenticationManager"/>
3. Instruct Spring OAuth2 to look up different oauth_client_table
If you look closely at the default spring-security.xml from the official Spring OAuth2 repo linked above, you will see the following chain of references
clientCredentialsTokenEndpointFilter bean
references
clientAuthenticationManager bean
references
clientDetailsUserDetailsService
references
clientDetails
And clientDetails is nothing but a list of fixed oauth clients declared at the end under <oauth:client-details-service id="clientDetails"> tag.
Alright, so the objective is to instruct Spring OAuth2 to read and store oauth_clients to/from a database.
If we do not need to customize the the default spring oauth database tables to meet our specific needs, then its quite easy and the process is as follow
Setup the default Spring OAuth2 database tables as shown in this link
In the spring-security.xml change the clientDetailsUserDetailsService to pass the default Spring OAuth2 org.springframework.security.oauth2.provider.client.JdbcClientDetailsService and declare the same as a bean, as shown below.
Defautlt Spring OAuth2 JdbcClientDetailsService bean definition
<bean class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService" id="myClientDetails">
<constructor-arg index="0">
<!-- This is your jdbc datasource, i.e. db details-->
<ref bean="dataSource" />
</constructor-arg>
</bean>
and now the clientDetailsUserDetailsService bean should look as follow
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="myClientDetails" />
</bean>
And everything else the stays the same. The above changes, will instruct the Spring OAuth2 to read oath_clients from the database (oauth_client_details) rather than hard-coded xml config.
What if, you wanted to modify the default oauth_client_details table to adda few custom columns to meet your specific needs, will in that case you need to make a different set of changes. So we have the following objective
Add extra columns to the default oauth_client_details table
given the following (in the default spring-security.xml)
clientCredentialsTokenEndpointFilter bean
references
clientAuthenticationManager bean
references
clientDetailsUserDetailsService
references
clientDetails
We need to transform the above workflow (or chain of references) in order for Spring OAuth2 to be able to access our new customized oauth_client_details database table. So the new workflow or chain of references should be similar to below
clientCredentialsTokenEndpointFilter bean (no change)
references
clientAuthenticationManager bean (no change)
references
clientDetailsUserDetailsService (to be updated)
references
clientDetails (to be replaced)
And to achieve the above, lets move from bottom to top. The default Spring OAuth2 uses org.springframework.security.oauth2.provider.ClientDetails to load oauth_client from the default oauth_client_details table. We need to provide a custom implementation for org.springframework.security.oauth2.provider.ClientDetails by implementing it hence, something as follow
public class MyClientDetails implements ClientDetails { ... }
Before we move on, I just wanted to mention that Spring OAuth2 already provides an implementation for the above interface meaning that we could make our life a lot easier by actually extending the only implementation of the above interface (ClientDetails) which is org.springframework.security.oauth2.provider.client.BaseClientDetails rather than implementing it from the beginning (leverage all that can be done from BaseClientDetails and add our own custom fields) hence, the MyClientDetails looks as follow then
public class MyClientDetails extends BaseClientDetails {
//fields representing custom column for oauth_client
//getters and setters
//make sure to call super() in the inherited constructors, before
//setting custom fields.
}
Alright, now that we have our own ClientDetails object, just like #2 we need to implement our own JdbcClientDetailsService that will get injected to clientDetailsUserDetailsService. In order to implement our own JdbcClientDetailsService let's look at the signature of the default method
public class JdbcClientDetailsService
extends Object
implements ClientDetailsService, ClientRegistrationService
As you can see, the above class implements ClientDetailsService & ClientRegistrationService interfaces. While implementing our own JdbcClientDetailsService I do not recommend extending the default JdbcClientDetailsService because there are quite a few private class variables (and methods) which will not be inherited hence, let's use the default implementation to write our own.
public class MyJdbcClientDetailsService implements ClientDetailsService, ClientRegistrationService {
//override loadClientByClientId method, query the custom
//oauth_client_details database table and populate the
//MyClientDetails object created above and return it.
//Implement other methods to CRUD oauth_clients
}
Now that you implemented MyJdbcClientDetailsService create a bean for it in spring-security.xml, in the following lines
Now inject the above bean to clientDetailsUserDetailsService, and looking into default spring-security.xml, we have the following
<!-- Original referencing hardcoded clients -->
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
And the above will need to be changed to as follow
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="myJdbcClientDetailsService" />
</bean>
There we go, now the chain looks as follow after specifying our own ClientDetailsService:
clientCredentialsTokenEndpointFilter bean (no change)
references
clientAuthenticationManager bean (no change)
references
clientDetailsUserDetailsService (ref updated)
references
myJdbcClientDetailsService (our customized client details service)
The above instructs the Spring OAuth2 to look up a customized database table for oauth_client details.
4. Using JWT Token and want to add extra claims
JWT Token or JSON Web Token can be used among three different actors of OAuth2 (Authorization server actor, Resource Server actor, Client actor) in order to communicate with each other in performing different actions relating to authorization and access of protected resources. The JWT token is used by Authorization server and it is signed using a public/private key and the objective is to make sure that the content of the JWT token do not get updated (unless someone have access to the private key). The basic workflow can be as follow (Let's assume password grant flow)
Client actor makes a request on behalf of the Resource owner actor (user) to the Authorization server actor asking for an OAuth2AccessToken
Authorization server actor verifies that the requesting client is trusted or not (by checking the requesting clients passed client_id and client_secret - the MyJdbcClientDetailsService is used to lookup the client), Once the client is verified and client secret matched, then it will verify the username and password (this could use the MyUserDetailsService to lookup the user in our database user table) that's also been passed by the Client actor (on behalf of user). If a user is found, then its password is matched (maybe using a custom Password encoder - i.e. BCrypt recommended due to slow hash function) and if all well, then it will retrieve the User's role and construct a JWT token, then sign it with it's own public/private key, store the JWT Token with client details in the database (oauth_access_token default table) and return a copy of the JWT Token to the requesting client.
The Client actor then sends the user's request to the Resource server asking for a protected resource passing along the JWT token. The Resource server validates that the JWT is valid and not tampered, and then accordingly serve the Client actor.
Above briefly describes how the JWT token is used by OAuth2. There is a ton of more details on JWT and varieties of JWT out there (signed, signed and encrypted, etc etc).
For more information on JWT implementation of Spring OAuth2, see the official repo here and JWT webpage.
Let's see, we have the following JWT
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
and we would like to include a set of scopes to the above token, so the Resource server actor know whether this user is allowed to make this request or not. The change could look as follow
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"scope": "read write delete"
}
To add custom claims (each of above key/value is referred to as claims), we need to create a class MyTokenEnhancer which implement org.springframework.security.oauth2.provider.token.TokenEnhacer interface and override it's enhance method OR extend org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter which in turn implements the default TokenEnhancer and override it's enhance method.
By overriding the enhance method, you can add custom claims to the OAuth2AccessToken. Please see the above linked repo for more details on this.
5.Develop custom implementation of OAuth2RequestValidator and inject it to the Token endpoint
For me, the oauth clients send a customized OAuth2Request and I needed more than the deafult DefaultOAuth2RequestValidator implementation hence, I had to write my own and implemented the org.springframework.security.oauth2.provider.OAuth2RequestValidator. Something in the following lines
public class MyOAuth2RequestValidator implements OAuth2RequestValidator {
//override the necessary methods
}
Now that we have created our own custom MyOAuth2RequestValidator how should we instruct the Token endpoint to use it using XML configuration? Well, this one took me a little time for figure it out. Looking into the default spring-security.xml we have the following
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
When we make an OAuth2 request to the /oauth/token endpoint, the request is mapped to ClientCredentialsTokenEndpointFilter first, and from there at some stage the request is delegated to org.springframework.security.oauth2.provider.endpoint.TokenEndpoint and if you look at the source code TokenEndpoint you will see the following
private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator();
Now to replace that with our Custom validator MyOAuth2RequestValidator we need to do the following
Create a bean that references our custom MyOAuth2RequestValidator and name give it id of "myOAuth2RequestValidator"
Update the <oauth:authorization-server> in the spring-security to use our custom validator from #1
See below the updated authorization-server tag
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler"
request-validator-ref="myOAuth2RequestValidator">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
And that's it. Now, every time the TokenEndpoint is hit, it will use our custom validator instead of default one.
6. Disable a grant flow
We might not use all of the available grant flows hence, make sense to disable those not used. Let's say, I don't want to use refresh-token grant flow (just an example) and to disable it we have to update the <oauth:authorization-server>
The authorization server with disabled refresh-token grant flow looks as follow
You can also disable other flows. Obviously you can get away with not disabling it because, if you do not support let's say Authorization Code grant flow then simply do not register an oauth_client that has a value of authorization_code in it's oauth_client_table (if default oauth table)'s authorized_grant_types column.
Also to share with you an experience that helped me understand Spring OAuth2, I actually debugged the Spring OAuth2 classes to understand how each workflow worked and kept track of all the classes that got hit during different grant flows. It's helpful to give you an overall understanding of how Spring OAuth2 works and then it will become less painful to implement your own OAuth2 implementation on top of Spring OAuth2.
7. Enable Verify token endpoint and Validate JWT Custom claims
If the Resource and Authorization server are not in the same server and not sharing the same database, then Resource server requires to double check with Authorization server after it receives a request for a resource to make sure that the token is still valid (this is useful when tokens don't expire too soon) and has the right permissions/claims. In order to achieve this Spring OAuth provides Check Token Endpoint that can be enabled by adding the following
check-token-enabled="true"
to the <oauth:authorization-server ...> element in the XML configuration file. Once the above is added, a POST request to {server-url}/oauth/check_token with a form parameter with key token and value JWT access token will instruct the Authorization server to validate that the token is valid. The default implementation does the default checks such as
Expiry date
Signature verification
Etc
And you will have to do a little bit of customization to validate your custom claims. See my other post in here for more details.
I wanted to know is there any way to add properties to JMS text Message in Spring Integration.
For example if we use normal JMS code we can always set properties to it using the below code.
message.setStringProperty( "AuctionType", "Reverse" );
Edit
I tried to add the header as given in Spring document but now i am getting same message Id for each message, but as i am intended to use it as ID, so i need it to be different for each message.
Below is my snapshot of Spring configuration.
<bean class="com.learn.util.RandomMsgId" id="randomMsgId" factory-method="getRndMsgId" scope="prototype"/>
<int:header-enricher input-channel="xmlToJMS"
output-channel="xmltoJMSwithId">
<int:header name="MsgId" ref="randomMsgId"/>
</int:header-enricher>
Use a <header-enricher/> to add custom headers to the spring integration message and they will be mapped to JMS headers.
See the documentation and here.
I'm trying to implement pre-authenicated security in our web application but I'm not sure how to do it correctly. There aren't that many examples out there. And the ones that are seem to have a much simpler setup than ours.
We get our authentication details in a request header as an XML with a firstname, lastname, user ID and an error tag, if any occured.
I'm extending AbstractPreAuthenticatedProcessingFilter and in its getPreAuthenticatedPrincipal() I extract the header, unmarshall it, and do some validation.
Now the questions:
If everything's OK, do I just return my unmarshalled shibboleth from getPreAuthenticatedPrincipal()?
If something's wrong, do I just throw a PreAuthenticatedCredentialsNotFoundException?
What do I return from getPreAuthenticatedCredentials()? Is "N/A" sufficient?
I suppose at some point I have t create an Authentication and a Principal.
Is this a good approach?
Principal dynamicUser = new DynamicUser(rijksregisterNummer);
List<SimpleGrantedAuthority> grantedAuthorities = Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
Authentication authentication = new AnonymousAuthenticationToken(rijksregisterNummer, dynamicUser, grantedAuthorities);
At what point (in which class) do I set it in the Spring Security?
What other classes do I need to extend?
How do I configure the Spring Security configuration XML? Like this? What am I missing?
<http>
<custom-filter position="PRE_AUTH_FILTER" ref="myPreAuthFilter" />
</http>
<bean id="myPreAuthFilter" class="my.package.MyPreAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider"/>
</authentication-manager>
External users go through pre-authentication (using an e-ID and card reader) and then hit our web application. Internal users however, have to authenticate with a uername and password, a normal authentication procedure.
How can I set it up that when there isn't an shibboleth (thus a login from our internal users), I can display a login form?
Lot's of question, I know. I hope you can guide me through.
This is an old question but still relevant. As said, there was many questions. What caught my eye was the observation that there are not many example implementations.
I've been playing with an implementation. You can find it here: https://github.com/klaalo/reqTokenAuth.
It is easy to mix and match with authentication methods on WebSecurityConfigurerAdapter so that you can have traditional form based authentication for legacy users.
The implementation is based on the setting where Apache mod_auth_openidc sits in front of the application. However, the implementation should work fine also with Shibboleth SP.
I didn't quite catch your sentiment about sending authentication details in HTTP Request headers as XML. Shibboleth SP is about SAML-authentication. You should leave the details about authentication for the SAML SP and only enjoy the benefits of readily authenticated user in your application. There's no need for unmarshalling the XML, Shibboleth does that for you. You get user details as clean Strings representing SAML attribute values in HTTP Headers or HttpServletRequest attributes (when Tomcat/AJP is used).
I am having a mule flow in which I am having a variable to which payload is copied as follows:
<set-variable variableName="originalPayload" value="#[payload]" doc:name="Variable" doc:description="Variable having copy of original payload present in soap request."/>
After this there is an interceptor that validates header of soap message and if validation fails then I need the above variable's data in interceptor to prepare custom fault message. Below is my configuration for Soap Proxy doing above:
<cxf:proxy-service port="XXX" namespace="XXX" service="XXX" payload="body" wsdlLocation="XXXX" doc:name="SOAP" doc:description="Soap proxy intercept soap request and apply header validation. Authentication and custom header will be validated for presence, content, and structure.">
<cxf:inInterceptors>
<spring:bean id="XXXX" parent="XXXX">
<spring:property name="sourceApplication" value="${sourceApplication}"/>
<spring:property name="originalMessage" value="#[originalPayload]"/>
</spring:bean>
</cxf:inInterceptors>
</cxf:proxy-service>
In above I need the value of originalPayload variable in originalMessage property of spring bean. If I can copy #[payload] directly it will work too. Above expression in spring property is not valid so it is not working.
Please suggest how to go for this.
Implementing Callable can be one option but I do not want to change the code written already unless there is no solution for above.
I tried to search for solution on this but could not find anything.
Thanks
Harish Kumar
The problem with your solution is that spring properties are set at configuration time whereas the #[payload] expression could be only resolved at runtime.
However within your interceptor you could retrieve the original payload from the CXF message by doing something like this:
MuleEvent event = (MuleEvent) message.getExchange().get(CxfConstants.MULE_EVENT);
Collection<Attachment> a = event.getMessage().getInvocationProperty("originalPayload");
You can refer to this interceptor as an example
I am new to spring integration. to make a rest webservice call, i have below configuration.
<int-http:outbound-gateway
url="#{appProperties['rootUrl']}#{appProperties['myMethod']}"
request-channel="myRequestChannel" reply-channel="myResponseChannel" >
</int-http:outbound-gateway>
But i should also pass authentication information (username and password) to make a webservice call. how can i send authentication information through http:outbound-gateway?
You have to use a custom ClientHttpRequestFactory and provide it to the adapter using the request-factory attribute.
Either use the CommonsClientHttpRequestFactory with a custom HttpClient, or subclass the SimpleClientHttpRequestFactory and override the prepareConnection method to add the credentials.
Googling "resttemplate basic authentication" will provide several examples, including http://blog.mitemitreski.com/2012/03/basic-authentication-with-resttemplate.html