Rest authentication on spring pac4j and cas oauth

1,628 views
Skip to first unread message

Binu Raj

unread,
Nov 30, 2015, 4:45:49 AM11/30/15
to pac4j-users
I am reffering spring-security-pac4j-demo(https://github.com/pac4j/spring-security-pac4j-demo) project for uri protection. Let me know one thing How can I access a page through rest. My scenario is here,
 
 1. I have a page "rest/RestView.jsp" which is protected with spring security.
<security:http pattern="/rest/**" entry-point-ref="casWrapperEntryPoint">
<security:csrf disabled="true"/>
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
        </security:http>
 2. Configured the casWrapperEntryPoint and casWrapperClient,
 
<bean id="casWrapperEntryPoint" class="org.pac4j.springframework.security.web.ClientAuthenticationEntryPoint">
        <property name="client" ref="casWrapperClient" />
    </bean>
    
    <bean id="casWrapperClient" class="org.pac4j.oauth.client.CasOAuthWrapperClient">
        <property name="key" value="this_is_the_key" />
        <property name="secret" value="this_is_the_secret" />
        <property name="casOAuthUrl" value="http://localhost:8080/cas2/oauth2.0" />
    </bean>
 The process is worked whwn I test with browser. Now I want to check with rest client. For that I follow these steps,
 
 1. Generate authentication ticket through rest client,
 
 2. Generate service ticket for acessing the rest,
 
 3. Accessing the rest,
 
But here the response is the code of cas login page. Is there any Token authenticatior I missed? Please check my springsecurity context.xml also.
And could you please help me to find out the issue?
securityContext.xml

Binu Raj

unread,
Nov 30, 2015, 7:16:20 AM11/30/15
to pac4j-users
Please refer this links,


But they are not using pac4j. Let me know how can I convert it into pac4j. Means How na I configure org.springframework.security.cas.ServiceProperties class? 

Jérôme LELEU

unread,
Nov 30, 2015, 8:54:53 AM11/30/15
to pac4j-users
Hi,

Your post is not clear: how you want to mix OAuth server support in CAS with the CAS REST API for example. Is the use of Spring Security mandatory for you?

Some information :

pac4j v1.8 handles web services authentications (direct clients) as well as UI authentications (indirect clients).

spring-security-pac4j is an extension to Spring Security to handle indirect clients: a CAS server (SSO flow), Facebook...

spring-webmvc-pac4j is a full security library for Spring Web MVC supporting direct and indirect clients.

The main difference between a direct client for web services and an indirect client for UI is that for web services, the credentials are expected to be on each HTTP request, no web session is required and no redirection (to an identity provider) is performed.

There is already a CasRestClient (different from the CasClient) to send the credentials to the CAS server REST API endpoint: https://github.com/pac4j/pac4j/tree/master/pac4j-cas/src/main/java/org/pac4j/cas/client/rest

Can you elaborate a little more about what you w

Jérôme LELEU

unread,
Nov 30, 2015, 8:56:01 AM11/30/15
to pac4j-users
Can you elaborate a little more about what you want to achieve?

Thanks.
Best regards,
Jérôme

Binu Raj

unread,
Dec 1, 2015, 12:01:49 AM12/1/15
to pac4j-users
I can explain my requirements with step by step.
1. I have a web application . We can call "DemoWebApp".
2. It have a jsp page hello.jsp which will dispay "Hello World". The path of the page is - rest/hello.jsp (rest is a folder under WEB-INF directory)
3. I want to protect my uri. if any one call mydomain/rest/hello.jsp without cas oauth authentication access denide will display.
4. If anyone not authenticated, the browser will redirect to cas oauth server and authenticate the user.Then redirect to hello.jsp and show its contents.
5. The last step is , I want to call the url(mydomain/rest/hello.jsp) from rest client. There the redirections and sessions are not required.
So user will send his username and password to cas oauth server. After succssfull login the server return a ticket for accessing the page. 
After that the rest call will be like this,
mydomain/rest/hello.jsp?ticket=XXXXXXXXXXXXXXXXXX
Is that clear? or let me know your comments?


On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Jérôme LELEU

unread,
Dec 1, 2015, 3:54:56 AM12/1/15
to Binu Raj, pac4j-users
Hi,

Steps 1 to 4 are easy to implement with spring-security-pac4j or any other pac4j implementation using the CasOAuthWrapperClient (indirect client).

Step 5: Assuming you can handle web session, you can use the FormClient with the https://github.com/pac4j/pac4j/blob/master/pac4j-cas/src/main/java/org/pac4j/cas/client/rest/CasRestFormClient.java as the authenticator. So you need to send your credentials to the callback url of your app: /callback?client_name=FormClient. Given that, you will be authenticated in your app and have a HttpTGTProfile from which you can request a service ticket for your app...
That said, you don't need to request a service ticket as you are already authenticated.

Thanks.
Best regards,
Jérôme



 

--
You received this message because you are subscribed to the Google Groups "pac4j-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Binu Raj

unread,
Dec 1, 2015, 4:24:01 AM12/1/15
to pac4j-users
Hi ,

1-4 tasks are already completed. In last step I have some more doubts,

I added these configurations to my springSecurity.xml,

1.  <bean id="restClient" class="org.pac4j.cas.client.rest.CasRestFormClient">
        <property name="loginUrl" value="http://localhost:8080/loginForm.jsp" />
        <property name="authenticator" ref="usernamePasswordAuthenticator" />
    </bean>

2.  <bean id="restEntryPoint" class="org.pac4j.springframework.security.web.ClientAuthenticationEntryPoint">
        <property name="client" ref="restClient" />
    </bean>
3. <security:http pattern="/rest/**"  entry-point-ref="restEntryPoint">
        <security:csrf disabled="true"/>
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
    </security:http>
My Callback URL is : http://localhost:9999/callback

It will return TGT{token}

After that I can use that token to access my protected rest uri like this,


Is that right?

On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Binu Raj

unread,
Dec 1, 2015, 5:13:26 AM12/1/15
to pac4j-users
Please check these configurations,

1. <bean id="restClient" class="org.pac4j.cas.client.rest.CasRestFormClient">
        <property name="authenticator" ref="restAuthenticator" />
    </bean>
2. <bean id="restAuthenticator" class="org.pac4j.cas.credentials.authenticator.CasRestAuthenticator">
   <property name="casServerPrefixUrl" value="http://localhost:8080/cas2" />
</bean>
 
3. <bean id="restEntryPoint" class="org.pac4j.springframework.security.web.ClientAuthenticationEntryPoint">
        <property name="client" ref="restClient" />
    </bean>
4. <security:http pattern="/rest/**" entry-point-ref="restEntryPoint">
        <security:csrf disabled="true"/>
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
    </security:http>
5. <bean id="clients" class="org.pac4j.core.client.Clients">
        <property name="callbackUrl" value="http://localhost:9999/callback" />
        <property name="clients">
        <list>
        <ref bean="facebookClient" />
        <ref bean="twitterClient" />
        <ref bean="googleClient" />
        <ref bean="formClient" />
        <ref bean="basicAuthClient" />
        <ref bean="casClient" />
        <ref bean="casWrapperClient" />
        <ref bean="samlClient" />
        <ref bean="restClient" />
        </list>
        </property>
    </bean>

And also please check the attached  log file. bean creation exception occurring.

On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:
rest_log.txt

Binu Raj

unread,
Dec 1, 2015, 11:15:32 AM12/1/15
to pac4j-users
Hi ,

I did the changes which you mentioned in the last mail. Means the client changed to CasRestFormClient. Then I will send a request from rest using call back url and login credentials.The authentication process is success. But I have some more doubt. I think it will work only in browser because of its session. The result value have no TGT{id}. So  How can I use this rest in mobile plat forms? or Can I use the secured rest  with the login TGT ticket?


On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Jérôme LELEU

unread,
Dec 2, 2015, 1:19:26 AM12/2/15
to Binu Raj, pac4j-users
Hi,

I'm not sure you really need the entry point as you will call the CasRestFormClient explicitly, but it's not a big matter, it could be some 403 default endpoint I guess.

The name of the CasRestFormClient is CasRestFormClient unless you give it another one by using the name property. Moreover, you should NEVER send credentials in a GET HTTP request, the username and password must be POSTed.

So you should POST (username, password) to http://localhost:9999/callback?client_name=CasRestFormClient.

Thanks.
Best regards,
Jérôme



--

Jérôme LELEU

unread,
Dec 2, 2015, 1:21:52 AM12/2/15
to Binu Raj, pac4j-users
Hi,

The error is obvious in your case:

failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.pac4j.cas.credentials.authenticator.CasRestAuthenticator]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.pac4j.cas.credentials.authenticator.CasRestAuthenticator.<init>()
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) ~[spring-beans-4.2.2.RELEASE.jar:4.2.2.RELEASE]

Thanks.
Best regards,
Jérôme


--

Jérôme LELEU

unread,
Dec 2, 2015, 1:22:30 AM12/2/15
to Binu Raj, pac4j-users
Hi,

Check my previous replies and let us know if it works.

Thanks.
Best regards,
Jérôme


--

Binu Raj

unread,
Dec 2, 2015, 1:25:39 AM12/2/15
to pac4j-users
Hi,

The authentication process is completed.After authentication the profile is displaying. And after the rest protected uri is working fine. This process working in the base of session.
But how can it work in other platforms like mobile. Let me know one more thing. Is there any way to access the protected uri with service ticket?


On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Binu Raj

unread,
Dec 2, 2015, 1:45:00 AM12/2/15
to pac4j-users
 As per your previous posts I did the rest opearion like this,
 
 
 And the response will be a jsp page of we application which shows the profile information. If I execute the protected rest uri it will work because of browser
 session. I think I can't use this methos for mobile plat forms. So My question is Is there any way to access the protected uri using the service ticket?
 For that is there any changes in configuration xml classes?

On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Jérôme LELEU

unread,
Dec 2, 2015, 8:17:18 AM12/2/15
to Binu Raj, pac4j-users
Hi,

With spring-security-pac4j, you can only use indirect clients, no REST support. So you must develop a solution based on Spring Security directly.

Thanks.
Best regards,
Jérôme


--

Binu Raj

unread,
Dec 2, 2015, 8:20:35 AM12/2/15
to pac4j-users
Ok, Spring security is not mandatory for me. So How can I implement a security system which support rest api using cas?


On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Jérôme LELEU

unread,
Dec 2, 2015, 8:39:42 AM12/2/15
to Binu Raj, pac4j-users
Hi,

I only reply to this latest post since there are several concurrent threads on the same topic.

1) define a CasOAuthWrapperClient like your already did

2) for REST support, credentials are meant to be sent for each HTTP request, in your case, username and password and to avoid performance issues, caching should occur. You can have another solution where you pass the credentials first and exchange them against a token you use afterwards. For solution 1 : username and password are passed for each request.

Use a CasRestBasicAuthClient or CasRestFormCient depending on how you pass the credentials and initialize them this way for example:

CasRestFormClient client = new CasRestFormClient(new LocalCachingAuthenticator(new CasRestAuthenticator("http://casserver"),1000, 10, TimeUnit.SECONDS));

Then, assuming you use spring-webmvc-pac4j for example, define the RequiresAuthenticationInterceptor on your /rest/** url with clientName = "CasOAuthWrapperClient,CasRestFormClient".

In a browser, calling the rest url should send you to your CAS server for OAuth authentication (UI). Posting with curl your data to /rest?client_name=CasRestFormClient should give an authenticated access to the endpoint (web services).

Thanks.
Best regards,
Jérôme



--

Binu Raj

unread,
Dec 2, 2015, 8:56:51 AM12/2/15
to pac4j-users
Hi,

I am choosing the second option which is exchange the username password to access token. Please reply my these questions too?

1. How can I get the access token?

2. Any new authenticator we need to write?

3. Do you have any example related to CasRestFormClient?

On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Binu Raj

unread,
Dec 3, 2015, 2:42:15 AM12/3/15
to pac4j-users
Hi LELEU,

I implemented the changes which you mentioned in your last mail. All works well. For accessing rest services I encoded the credentials and send as
header. I need another method, How can I convert the credentials to access token? Means First I will send the credentials to cas server and it will return a access token. Then I will use this token to access the rest. Is that possible?

On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Jérôme LELEU

unread,
Dec 3, 2015, 5:10:09 AM12/3/15
to Binu Raj, pac4j-users
Hi,

After posting your credentials to the CasRestFormClient, you are authenticated for the current request so you can create tokens on your own if you want.
Though, I would recommend using the JwtGenerator to generate a token from the user profile (I guess you need a new endpoint with the CasRestFormClient where you post your CAS credentials and get this token in return) and add a new ParameterClient with the JwtAutenticator for authentication and call your url with the token: /rest?client_name=ParameterClient&token=xxx

Thanks.
Best regards,
Jérôme



--

Binu Raj

unread,
Dec 3, 2015, 8:16:25 AM12/3/15
to pac4j-users
Hi,

Thanks for your reply. I am getting an exception when I am trying to generate JWT tokens. Please check the attachment log and let me know your comments?


On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:
jwt-log.txt

Jérôme LELEU

unread,
Dec 3, 2015, 9:30:07 AM12/3/15
to Binu Raj, pac4j-users
Hi,

The error is: Couldn't create AES/GCM/NoPadding cipher: Illegal key size

There can be two possible reasons: bad key length on your side, it must be 32 characters or you need unlimited strength in encryption: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

Thanks.
Best regards,
Jérôme



--

Binu Raj

unread,
Dec 3, 2015, 10:38:40 AM12/3/15
to pac4j-users
Hi ,

I checked the spring-pac4j-mvc source. It have the same  functionality to generate jwt tokens. That is not working for me. The same error is occurring. What will be issue?

On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Jérôme LELEU

unread,
Dec 3, 2015, 10:41:24 AM12/3/15
to Binu Raj, pac4j-users
Hi,

JWT support is part of pac4j and will work the same way in any pac4j implementation.
Did you check what I said in my previous post: key size or strength encryption policy of the JVM?

Thanks.
Best regards,
Jérôme


--

Binu Raj

unread,
Dec 3, 2015, 11:38:52 AM12/3/15
to pac4j-users
Yes. I increased the token strength and now generating the token. Thanks


On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Binu Raj

unread,
Dec 7, 2015, 12:24:50 AM12/7/15
to pac4j-users
Hi,

I found one problem in spring-webmvc-pac4j-demo. I your example genarate jwt-token is working only after authentication. But I tried with another way. These are the steps I invoked,
1. create a url for rest login. The creadentials are in the form of header. And the authentication send to local cas server.
@RequestMapping("/rest-login/index.html")
public String restAuthenticator(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {
//return protectedIndex(request, response, map);
final WebContext context = new J2EContext(request, response);
final UserProfile profile = getProfile(context);
final JwtGenerator generator = new JwtGenerator("12345678901234567890123456789012");
String token = "";
if (profile != null) {
token = generator.generate(profile);
}
map.put("token", token);
return "jwt";
}
Configurations :- 

<mvc:interceptor>
<mvc:mapping path="/rest-login/*" />
<bean class="org.pac4j.springframework.web.RequiresAuthenticationInterceptor">
<constructor-arg name="config" ref="config" />
<constructor-arg name="clientName" value="CasRestBasicAuthClient" />
</bean>
</mvc:interceptor>
<bean id="casRestBasicAuthClient" class="org.pac4j.cas.client.rest.CasRestBasicAuthClient">
<constructor-arg name="authenticator" ref="casRestAuthenticator" />
<constructor-arg name="headerName" value="Authorization"/>
<constructor-arg name="prefixHeader" value="Basic" />
</bean>
<bean id="casRestAuthenticator" class="org.pac4j.cas.credentials.authenticator.CasRestAuthenticator">
<constructor-arg name="casServerPrefixUrl" value="http://localhost:8080/cas2/" />
</bean>
2. Then send the request for login
The response is a jwt token. It is working as expected.
3. Secured a url with ParameterClient
<mvc:interceptor>
            <mvc:mapping path="/rest/*" />
            <bean class="org.pac4j.springframework.web.RequiresAuthenticationInterceptor">
                <constructor-arg name="config" ref="config" />
                <constructor-arg name="clientName" value="ParameterClient" />
            </bean>
        </mvc:interceptor>
4. Then access the secured url from rest client
5. Internal error. The profile is null. The system can't access the profile related to this token. 
NB :- I checked the login cas login from browser. And then generate the token then try with rest client. That time an error is occured,
java.lang.ClassCastException: org.pac4j.cas.profile.CasProfile cannot be cast to org.pac4j.http.profile.HttpProfile
Please check from your side and let me know your comments?


On Monday, 30 November 2015 15:15:49 UTC+5:30, Binu Raj wrote:

Jérôme LELEU

unread,
Dec 7, 2015, 6:59:07 AM12/7/15
to Binu Raj, pac4j-users
Hi,

It looks good. I assume your ParameterClient is properly defined with the "token" parameter and the appropriate JwtAuthenticator. It should work.

Can you turn on DEBUG logs on org.pac4j and post them here to see what's going on for step 5?

Thanks.
Best regards,
Jérôme


--

Binu Raj

unread,
Dec 7, 2015, 7:09:44 AM12/7/15
to pac4j-users
Hi,

I noticed one thing. I print the profile in console inside the protectedIndex function and invoke these steps,

protected String protectedIndex(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {
        final WebContext context = new J2EContext(request, response);
        UserProfile profile = getProfile(context);
        System.out.println(profile);
        map.put("profile",profile);
        return "protectedIndex";
    }

1. Acces the localhost from browser and success full login with cas server, the console displays,
<CasProfile> | id: jleleu | attributes: {isFromNewLogin=true, authenticationDate=Mon Dec 07 17:08:34 IST 2015, longTermAuthenticationRequestTokenUsed=false} | roles: [] | permissions: [] | isRemembered: false |
2. Login from rest client with encoded credentials to rest-login
The out put is only : jleleu
It have no class instance. Just "jleleu" string is showing. Is there any problem?

Binu Raj

unread,
Dec 7, 2015, 7:55:40 AM12/7/15
to pac4j-users
Hi,

 I can't find out the issue could you please help me to solve this? The console is like this when access the secured url with query string token,

SPRING WEB PAC4J DEMO 18:21:12.730 [qtp447320069-19] DEBUG o.p.s.w.RequiresAuthenticationInterceptor - credentials: <TokenCredentials> | token: eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiZGlyIn0..VFlqV7zFR9cuJUWV.KuOkbkY_YI7EEIXgsBxmOCbfUo45vXFElJiYnzWN76sfhuJt1lc_3tSTKKOjm2HRGdBCY6gVd76jjASCu_rbDNjGCbQLctZqWPw9FaH2EENoXuTTGCpf3NMJ_ivNxgbqnhu6VQACQp4ZwFb5_l8e3gs-JRnlyNf98Y0hPBpNMNLb7nrjkqPmrRXcZfzuVROOgEyESbVHojFNME4.7Hb8RJ3NlVOTeeGhDt9Dpw | clientName: ParameterClient |
SPRING WEB PAC4J DEMO 18:21:12.730 [qtp447320069-19] DEBUG o.p.s.w.RequiresAuthenticationInterceptor - profile: null
SPRING WEB PAC4J DEMO 18:21:12.730 [qtp447320069-19] DEBUG o.p.s.w.RequiresAuthenticationInterceptor - authorizerName: null
SPRING WEB PAC4J DEMO 18:21:12.730 [qtp447320069-19] DEBUG o.p.s.w.RequiresAuthenticationInterceptor - grant access

Binu Raj

unread,
Dec 7, 2015, 8:31:12 AM12/7/15
to pac4j-users
Hi,

How can I turn on DEBUG logs on org.pac4j. Now I can see some logs which is for cas and perfStats. Nothing  is related to JwtAuthenticator.

Binu Raj

unread,
Dec 7, 2015, 11:41:34 AM12/7/15
to pac4j-users
Hi,

I wrote some custom messages to understand whats is happening inside the jwt authenticator. The function will changed to :

 public void validate(TokenCredentials credentials) {
    System.out.println("=====START VALIDATION=====");
    System.out.println("=====SECRET : " + secret);
        CommonHelper.assertNotBlank("secret", secret);

        final String token = credentials.getToken();
        System.out.println("========TOKEN : "+ token);
        boolean verified = false;
        SignedJWT signedJWT = null;

        try {
            // Parse the token
            JWT jwt = JWTParser.parse(token);
            
            System.out.println("=========PARSE TOKEN : " + jwt);

            if (jwt instanceof SignedJWT) {
                signedJWT = (SignedJWT) jwt;
            } else if (jwt instanceof EncryptedJWT) {
                JWEObject jweObject = (JWEObject) jwt;

                // Decrypt with shared key
                jweObject.decrypt(new DirectDecrypter(this.secret.getBytes("UTF-8")));

                // Extract payload
                signedJWT = jweObject.getPayload().toSignedJWT();
                System.out.println("===========SIGNED JWT :" + signedJWT);
            } else {
                throw new TechnicalException("unsupported unsecured jwt");
            }
            
            verified = signedJWT.verify(new MACVerifier(this.secret));
            
            System.out.println("==========VERIFIED : " + verified);
        } catch (final Exception e) {
            throw new TechnicalException("Cannot decrypt / verify JWT", e);
        }

        if (!verified) {
            final String message = "JWT verification failed: " + token;
            throw new CredentialsException(message);
        }

        try {
            final JWTClaimsSet claimSet = signedJWT.getJWTClaimsSet();
            System.out.println("==========CLAIM SET :" + claimSet.getSubject() +" : " + claimSet.getClaims());
            final UserProfile profile = ProfileHelper.buildProfile(claimSet.getSubject(), claimSet.getClaims());
            credentials.setUserProfile(profile);
            System.out.println("=================PROFILE : " + profile);
        } catch (final Exception e) {
            throw new TechnicalException("Cannot get claimSet", e);
        }
    }

And the out put from console when I tried to access the uri from rest client with token is,

=====START VALIDATION=====
=====SECRET : 12345678901234567890123456789012

========TOKEN : eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiZGlyIn0..DTtAydBrnpSdjH4o.MY3-eCQZWxbYms4oAm16G9nAagzzSiETrjCGdddMgrp4o5dumTVNxqwn6QHDmwXoBHXbx1Su8dVsLgmC-5ttY1f-mSUVWA6qKkZP2sCDlwUm_kPlYF90kSVC2uxfro66hEj7fg2zb3MR3kNGuLkGhVR6NtCuO51oyR-OTM8QHqACQWnIz-QFSWFnQaZYUca6nJ6MfL8VrTETYJ8.33ngcyG8mfMTdFz607v1ng

=========PARSE TOKEN : com.nimbusds.jwt.EncryptedJWT@3d3eabb
===========SIGNED JWT :com.nimbusds.jwt.SignedJWT@512a49ee
==========VERIFIED : true
==========CLAIM SET :HttpTGTProfile#null : {sub=HttpTGTProfile#null, iss=JwtGenerator, iat=Mon Dec 07 21:39:55 IST 2015}
=================PROFILE : null

It is throwing no errors..And could you please find out the actual issue?

Binu Raj

unread,
Dec 8, 2015, 1:16:56 AM12/8/15
to pac4j-users
Hi,

I am very dissapointed to say that the "spring-webmvc-pac4j" is not wroking with CasRestAuthenticator. I am spending 4 days to find out the problem.
But I couldn't find out the problem yet. I have some doubts in profile manger. Please check the steps,
1. Access the url - http://localhost:8080/dba/index.html from rest client with encoded credentials.The /dba/* is protected with DirectBasicAuthClient.
   So it validate using SimpleTestUsernamePasswordAuthenticator.
The result is : <HttpProfile> | id: jleleu | attributes: {username=jleleu} | roles: [] | permissions: [] | isRemembered: false |
The profile is an object of HttpProfile class.
2. Access the url - http://localhost:8080/rest-login/index.html from rest client with encoded credentials.The /rest-login/* is protected with CasRestBasicAuthClient.
   So it validate using CasRestAuthenticator.
The result is : jleleu
The profile is a string. No object intance.
Is this is an expected behaviour? I think the profile may be the instance of HttpTGTProfile.
3. After getting cas rest profile I am generating a JWT token for accessting parameter client protected url.The token generation is successfull
4. Access the url - http://localhost:8080/rest/index.html from rest client with jwt token as query string.The /rest/* is protected with ParameterClient.
   So it validate using JwtAuthenticator.
   
5. The result and profile is null. Don't know the issue.
6. For tracking the error I have create a new JwtAuthenticator which name is CustomJwtAuthenticator.
7. I have made small changes to display the values inside validate function, like this
8. The out put in console will look like,
=====START VALIDATION=====
=====SECRET : 12345678901234567890123456789012
========TOKEN : eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiZGlyIn0..NZcLdzTvccPFgK0T.-wm4d0sIYDJCupmeKK6iWuq4pHdA4me8mjNUJ-Q22qxPapbXXAj2i6LkYV4pd_G2WWhKKJZLWaxa3XcUT2bnnptdP4LiEcHeEmzNv23I_WFbnKzZepSh2rVhvYY5Gn9kKL1pBMlwzUr5wfuoMRN3uDuUu516XhgHltczF0XLqWxudYbaQ5N7dmV0khv0-7GwNF9jlUfMDDuJ0mg.R2gJycg6RjBKKYhxO7plYQ
=========PARSE TOKEN : com.nimbusds.jwt.EncryptedJWT@323160cb
===========SIGNED JWT :com.nimbusds.jwt.SignedJWT@6cecf9cf
==========VERIFIED : true
==========CLAIM SET :HttpTGTProfile#null : {sub=HttpTGTProfile#null, iss=JwtGenerator, iat=Tue Dec 08 11:08:36 IST 2015}
=================PROFILE : null
I can't find out where is the issue? Do you have tried with cas rest authenticator. Other wise please try. I am using "cas-pac4j-oauth-server-demo" for server.
Please try to invoke these procedure. I am sure some thing is missing here. Please check and let me know your comments.
I am waiting for your reply.....

Jérôme LELEU

unread,
Dec 8, 2015, 3:26:19 AM12/8/15
to Binu Raj, pac4j-users
Hi,

You should always be able to enable DEBUG logs in your application as well as do some debugging, otherwise finding any problem is a nightmare.

I won't say there is never a bug in pac4j, but things are generally tested thoroughfully in the demos and the fact supports are tested multiple times in the demos helps to find and fix bugs.

That said:

1) OK. As expected

2) It should be a HttpTGTProfile and not a String of course. If it's not the case, I'm not surprised if you have many issues after that. I'm going to update today my online CAS server to support REST calls and then the spring-webmvc-pac4j-demo to use a CasRestBAsicAuthClient to see if it works or not.

Stay tuned.

Thanks.
Best regards,
Jérôme






--

Jérôme LELEU

unread,
Dec 8, 2015, 6:27:56 AM12/8/15
to Binu Raj, pac4j-users
Hi,

You were right: there was something wrong in the CAS REST support. The profile was not a String, but the toString just returns the username. No identifier was set in the HttpTGTProfile, so it should explain most of your problems. It's now fixed in the current 1.8.1-SNAPSHOT: https://github.com/pac4j/pac4j/commit/1e4c27fe0a5c2c1a5e4ce9e32fda9cd9e1a39213

I updated the spring-webmvc-pac4j-demo as well to add a link to test the CAS REST support: https://github.com/pac4j/spring-webmvc-pac4j-demo/commit/497dff8cac35fcbdfe3de071ce80f67f961e274f

Just let me know if it works correctly now.

Thanks.
Best regards,
Jérôme


2015-12-08 7:16 GMT+01:00 Binu Raj <binur...@gmail.com>:

--

Binu Raj

unread,
Dec 8, 2015, 8:16:53 AM12/8/15
to pac4j-users
Hi,

I import the new maven project. I checked the cas authenticator class by clicking from demo servlet. But it is not upadted.  i think the jar file is from m2 directory. Which jar I want to delete from m2 directory?

Jérôme LELEU

unread,
Dec 8, 2015, 8:21:52 AM12/8/15
to Binu Raj, pac4j-users
Hi,

Delete the org/pac4j directory in your m2/repository. The new dependencies will be automatically downloaded.

Best regards,
Jérôme


--

Binu Raj

unread,
Dec 8, 2015, 8:33:32 AM12/8/15
to pac4j-users
Thanks LELEU. Thanks a lot. It is working now. again Thanks for your wonder full support. And I need another question to you. How can I set the expiry time and refresh token?
Is that possible?

Jérôme LELEU

unread,
Dec 8, 2015, 10:00:57 AM12/8/15
to Binu Raj, pac4j-users
Hi,


So we could certainly add something on the authenticator side to handle expiration. Feel free to submit some pull request for that.

Thanks.
Best regards,
Jérôme



--

Binu Raj

unread,
Dec 10, 2015, 6:00:07 AM12/10/15
to pac4j-users
Hi,

I have some doubts in issue time in jw tokens. Please check theese steps and clarify my doubt,
1. generate jwt token using encoded credentials
<HttpTGTProfile> | id: jleleu | attributes: {} | roles: [] | permissions: [] | isRemembered: false |
2. Then access the secured url and dispays the profile. That time some extra attribues added.
<HttpTGTProfile> | id: jleleu | attributes: {sub=HttpTGTProfile#jleleu, iss=JwtGenerator, iat=Thu Dec 10 11:24:16 IST 2015} | roles: [] | permissions: [] | isRemembered: false |
3. Then re generate the JWT token using this profile.
The token creation success. Working as expected.
4. Then displays the profile.
The out put is same. The issued / generated time not updated. How can I update?
<HttpTGTProfile> | id: jleleu | attributes: {sub=HttpTGTProfile#jleleu, iss=JwtGenerator, iat=Thu Dec 10 11:24:16 IST 2015} | roles: [] | permissions: [] | isRemembered: false |

Jérôme LELEU

unread,
Dec 10, 2015, 7:19:14 AM12/10/15
to Binu Raj, pac4j-users
Hi,

Good point. I haven't made the test to re-encode a decoded JWT token, but I guess the original iat overrides any new issue time as it is restored as a user attribute? Thus, the issued time never changes.

Any concern with that?

Thanks.
Best regards,
Jérôme


--

Binu Raj

unread,
Dec 10, 2015, 7:22:58 AM12/10/15
to pac4j-users
Ok. I implemented the token expiration functionality using  issued time. How can I get  new token using the old one?

Binu Raj

unread,
Dec 10, 2015, 7:34:13 AM12/10/15
to pac4j-users
Hi,

I have created a controller for refreshing the expiry tokens. Could you please check the below code and let me know your comments. Its working perfectly as expected.

@Controller
public class TokenRefreshController {
private final static String CLIENT_NAME = "ParameterClient";
private final static String KEY = "12345678901234567890123456789012";
protected static final Map<String, Object> EMPTY_MAP = new HashMap<String, Object>();

@RequestMapping("/token/refresh")
    public String refresh(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {
return protectedIndex(request, response, map);
    }
public String protectedIndex(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {
request.getQueryString();
String token =  request.getParameter("token");
        UserProfile profile = getProfile(token);
        String newtoken = "";
        final JwtGenerator generator = new JwtGenerator(KEY);
        if (profile != null) {
        newtoken = generator.generate(profile);
        }
        map.put("token", newtoken);
        return "jwt";
}
private UserProfile getProfile(String token){
        boolean verified = false;
        SignedJWT signedJWT = null;
        try {
            // Parse the token
            JWT jwt = JWTParser.parse(token);
            if (jwt instanceof SignedJWT) {
                signedJWT = (SignedJWT) jwt;
            } else if (jwt instanceof EncryptedJWT) {
                JWEObject jweObject = (JWEObject) jwt;
                // Decrypt with shared key
                jweObject.decrypt(new DirectDecrypter(KEY.getBytes("UTF-8")));

                // Extract payload
                signedJWT = jweObject.getPayload().toSignedJWT();
            } else {
                throw new TechnicalException("unsupported unsecured jwt");
            }
            verified = signedJWT.verify(new MACVerifier(KEY));
        } catch (final Exception e) {
            throw new TechnicalException("Cannot decrypt / verify JWT", e);
        }
        if (!verified) {
            final String message = "JWT verification failed: " + token;
            throw new CredentialsException(message);
        }
        UserProfile profile =  null;
        try {
            final JWTClaimsSet claimSet = signedJWT.getJWTClaimsSet();
            profile = ProfileHelper.buildProfile(claimSet.getSubject(), EMPTY_MAP);
}catch (final Exception e) {
       throw new TechnicalException("Cannot get claimSet", e);
   }
        return profile;

Jérôme LELEU

unread,
Dec 11, 2015, 3:53:08 AM12/11/15
to Binu Raj, pac4j-users
Hi,

The JWTAuthenticator returns a user profile from a token and the JWTGenerator does the opposite.
Thanks.
Best regards,
Jérôme


--

Jérôme LELEU

unread,
Dec 11, 2015, 3:56:32 AM12/11/15
to Binu Raj, pac4j-users
Hi,

It looks like a copy/paste from the JWTAuthenticator. You can make your life easier by directly using it:

TokenCredentials c = new TokenCredentials(token);
jwtAuthenticator.validate(c);
UserProfile u = c.getUserProfile();

Thanks.
Best regards,
Jérôme



--

Binu Raj

unread,
Dec 16, 2015, 1:11:15 AM12/16/15
to pac4j-users
Hi ,

I have few questions related to spring-webmvc-pac4j to complete my doubts,

1. Is JWT Token is CSRF Supported? How it works in rest clients?
 
2. Is there any mechanism to store  the JWT Tokens to DB? Or Are we using  only encryption and decryption of tokens?
 
3. I have authenticated with cas rest client and result is a jwt token. I repeated the step twice and now I have 2 tokens.
Then I access the protected uri with the first one. It will work. But I want to destroy the first one and latest token is only valid .
Is that possible?

Misagh Moayyed

unread,
Dec 16, 2015, 1:31:22 AM12/16/15
to pac4j-users

I’ll answer what I can:

 

Generally, the management of JWTs are your own responsibility. There is no storage requirement for pac4j AFAIK.

 

How can the result of a CAS REST client call be a JWT? You get a TGT, and then you request an ST based on that TGT, you validate that ST and you get the principal. Where does JWT come in?

 

--

You received this message because you are subscribed to the Google Groups "pac4j-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

This email has been sent from a virus-free computer protected by Avast.
www.avast.com

Binu Raj

unread,
Dec 16, 2015, 1:46:19 AM12/16/15
to pac4j-users
Hi,

Actually my concept is client send an encoded credentials to authenticate with cas. The result of the authentication  will resturn a jwt token. 
The configuration like this,
<mvc:interceptor>
            <mvc:mapping path="/rest-login/*" />
            <bean class="org.pac4j.springframework.web.RequiresAuthenticationInterceptor">
                <constructor-arg name="config" ref="config" />
                <constructor-arg name="clientName" value="CasRestBasicAuthClient" />
            </bean>
        </mvc:interceptor>
<bean id="casAuthenticator" class="org.pac4j.cas.credentials.authenticator.CasRestAuthenticator">
<constructor-arg name="casServerPrefixUrl" value="http://localhost:8080/cas2" /> <!-- amxlbGV1OmpsZWxldQ==  -->
</bean>

<bean id="casRestBasicAuthClient" class="org.pac4j.cas.client.rest.CasRestBasicAuthClient">
<constructor-arg name="headerName" value="Authorization" />
<constructor-arg name="prefixHeader" value="Basic " />
<constructor-arg name="authenticator" ref="casAuthenticator" />
</bean>
@RequestMapping("/rest-login/index.html")
public String restAuthenticator(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {
//return protectedIndex(request, response, map);
final WebContext context = new J2EContext(request, response);
final UserProfile profile = getProfile(context);
System.out.println(profile);
final JwtGenerator generator = new JwtGenerator("12345678901234567890123456789012");
String token = "";
if (profile != null) {
token = generator.generate(profile);
}
System.out.println(profile);
map.put("token", token);
return "jwt";
}
After getting this token access the uri which will secure with parameter client. like this,
<mvc:interceptor>
            <mvc:mapping path="/rest/*" />
            <bean class="org.pac4j.springframework.web.RequiresAuthenticationInterceptor">
                <constructor-arg name="config" ref="config" />
                <constructor-arg name="clientName" value="ParameterClient" />
            </bean>
        </mvc:interceptor>
Did you get that idea? Here my question is how can I destroy/logout the previous generated tokens?

Misagh Moayyed

unread,
Dec 16, 2015, 2:04:26 AM12/16/15
to pac4j-users

CAS itself has no knowledge of JWTs, yet. So if you have extended your CAS server to keep track of JWTs for SSO, you need to further that extension to destroy those JWTs when SSO ends (i.e. /cas/logout)

 

But, if you authenticate with CAS via a Rest and then in YOUR APP create a JWT that represents that profile, then it all depends on how you manage that JWT and your app session. That has nothing to do with pac4j and/or CAS. If your JWT in your app is bound to your application session, you can kill your app session, and you will have logged out. CAS Rest does not establish an SSO session, so cas/logout won’t do anything for you. The best you can do is kill the TGT that the rest client used to get you the profile.

 

From: pac4j...@googlegroups.com [mailto:pac4j...@googlegroups.com] On Behalf Of Binu Raj
Sent: Tuesday, December 15, 2015 11:46 PM
To: pac4j-users <pac4j...@googlegroups.com>
Subject: Re: Rest authentication on spring pac4j and cas oauth

 

Hi,

--

You received this message because you are subscribed to the Google Groups "pac4j-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Binu Raj

unread,
Dec 16, 2015, 2:34:54 AM12/16/15
to pac4j-users
Yes, I am talking about the process for killing the token/TGT. it is only possible in web application not in cas server.  Let me know how can I do that? Is there any example code or reference link?

Misagh Moayyed

unread,
Dec 16, 2015, 3:16:25 AM12/16/15
to pac4j-users

Well if you have the TGT, the rest client allows you to destroy it:

https://github.com/pac4j/pac4j/blob/master/pac4j-cas/src/main/java/org/pac4j/cas/client/rest/AbstractCasRestClient.java#L68

 

Again, note that killing the TGT does not equal logging out. CAS rest does not establish SSO for you. It’s rest. It’s stateless.

 

From: pac4j...@googlegroups.com [mailto:pac4j...@googlegroups.com] On Behalf Of Binu Raj
Sent: Wednesday, December 16, 2015 12:35 AM
To: pac4j-users <pac4j...@googlegroups.com>
Subject: Re: Rest authentication on spring pac4j and cas oauth

 

Yes, I am talking about the process for killing the token/TGT. it is only possible in web application not in cas server.  Let me know how can I do that? Is there any example code or reference link?

--

You received this message because you are subscribed to the Google Groups "pac4j-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jérôme LELEU

unread,
Dec 16, 2015, 4:40:29 AM12/16/15
to Misagh Moayyed, pac4j-users
Hi,

Regarding CSRF, it has no link with JWT tokens in pac4j.

You can specify some security filters in the authorizerName. From the README:

authorizerName (optional): the list of authorizer names (separated by commas) used to check authorizations. If the user is not authorized, a 403 HTTP error is returned. By default (if blank), the user only requires to be authenticated to access the resource. The following authorizers are available by default:
  • hsts to use the StrictTransportSecurityHeader authorizer, nosniff for XContentTypeOptionsHeadernoframe forXFrameOptionsHeaderxssprotection for XSSProtectionHeadernocache for CacheControlHeader orsecurityHeaders for the five previous authorizers
  • csrfToken to use the CsrfTokenGeneratorAuthorizer with the DefaultCsrfTokenGenerator (it generates a CSRF token and adds it to the request and save it in the pac4jCsrfToken cookie), csrfCheck to check that this previous token has been sent as the pac4jCsrfToken header or parameter in a POST request and csrf to use both previous authorizers.


Thanks.
Best regards,
Jérôme

Binu Raj

unread,
Dec 22, 2015, 6:46:07 AM12/22/15
to pac4j-users
Hi,

I have build the spring-webmvc-pac4j-demo and cas-pac4j-oauth-server-demo with jetty. When I am running spring-webmvc-pac4j-demo web application there is a jetty plugin for run the server also. like this,
    <contextHandlers>
                        <contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
                            <war>${basedir}/../cas-pac4j-oauth-server-demo/target/cas-pac4j-oauth-server-demo.war</war>
                            <contextPath>/cas2</contextPath>
                        </contextHandler>
                    </contextHandlers>
So the "/cas2" is for oauth server.
Now I am moving in this into tomcat7 server. For that I copy and paste two war files of these applications in to web apps folder of tomcat.
But there is no lnk related to server context path. So I am facing some issues. How can I move the war files to tomcat?

Jérôme LELEU

unread,
Dec 22, 2015, 6:49:50 AM12/22/15
to Binu Raj, pac4j-users
Hi,

You build the demo (mvn clean package) and get two WARs: the cas-pac4j-oauth-client-demo is to to be run on /cas and the cas-pac4j-oauth-server-demo on /cas2

Best regards,
Jérôme


--

Binu Raj

unread,
Dec 22, 2015, 7:07:42 AM12/22/15
to pac4j-users
Hi,

I have one parent project and server and client are the child projects. I am attaching 3 pom.xml here for confirmation.
I build the war files and deployed in tomcat. But when I hit in browser "/cas" nothing is loading. 
1. cas-pac4j-oauth-demo - parent - pom1.xml
2. cas-pac4j-oauth-server-demo - child - pom2.xml
3. cas-pac4j-webmvc - child - pom3.xml
pom3.xml
pom1.xml
pom2.xml
Reply all
Reply to author
Forward
0 new messages