Message Boards

Integrating external Idp (auth server) with Liferay 7.2 using Oauth2.0

Kevin Matthews, modified 3 Years ago.

Integrating external Idp (auth server) with Liferay 7.2 using Oauth2.0

Expert Posts: 253 Join Date: 1/25/16 Recent Posts

Hi I am currenty having issues integrating my application using an external IDP (Ping). Below is my use case Oauth2 flow:

  1. The user requests a page on the portal URL.
  2. When click on the portal URL link  the user get redirects to the Identity Provider login screen to prompt for userid and password
  3. The IDP authenticates the user via Oauth2 and kerbose
  4. The user is redirected back to the portal with an authorization code
  5. The portal application fetches the Authorization code by make a POST  to called to recieve the Ouath2 JSON web token data from external IDP.
  6. Finally, the liferay portal appplication decode the token and uses the emailAddres to Autologin to authorize the user using liferay AutoLogin API.

The problem is I need to know how to get to my landing page as an Administrator or non admin user when the authentication is successful. The authenitcation was successful because the credetials were returned and i did not recieve null pointer exception. If I set AUTO_LOGIN_REDIRECT to a private page I get error message. Also, if I remove setting the attribute AUTO_LOGIN_REDIRECT I need to know if Autlogin will redirect to my default landing page configured in Admintration panel?

2020-10-27 14:13:24.398 ERROR [default task-3][AutoLoginFilter:258] Current URL /c/portal/login?code=unlk5SjM4kNVL0TymSRBx1r3TNbOu-gfXE1aZNpR generates exception: UT010019: Response already commited

Below is my code snippet:


@Component(
         immediate = true,
         service = AutoLogin.class
    )
public class AutoLoginService implements AutoLogin {
    
    private static final Log _log = LogFactoryUtil.getLog(AutoLoginService.class);
    @Override
    public String[] handleException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
            Exception e) throws AutoLoginException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String[] login(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws AutoLoginException {
        User user = null;
        String email = null;
         String authCode = null;
         long companyId = 0;
         String[] credentials = null;
        try {
            companyId = PortalUtil.getCompanyId(httpServletRequest);
            _log.info("COMPANY ID =["+companyId+"]");

             //Call Authorization server using Oauth2 Auth Endpoint
             Response clientResponse =   ClientBuilder.newClient().target(OauthBaseUrl)
                        
                      .path(OAuthAthorizationEndpoint)
                      .queryParam("client_id", "XXXX")
                      .queryParam("redirect_uri", "http://localhost:8081/c/portal/login")
                      .queryParam("response_type", "code")
                      .queryParam("grant_type", "autorization_code")
                      .queryParam("scope", " ")
                      .queryParam("client_secret", "XXXXXX")
                      .request(MediaType.APPLICATION_JSON_TYPE)
                      .header("X-XSRF-Header", "XXXXX")
                      .get();
              //Get auth Server Login Screen - Redirect to authServer Login Screen
              if(clientResponse.getStatus() == 302) {
                  httpServletResponse.sendRedirect("OauthBaseUrl&callbackURI=locahost:8081/c/portal/login");
             

            //Get Auth Code - After login AUth server, extract the Auth code from query param in URL from the response
                authCode = httpServletRequest.getParameter("code");
                 if (authCode != null) {
                      _log.info("CODE =["+authCode+"]");
                      //Fetch for token making a POST request using the AuthCode
                     String token = fetchOaAuth2Token(authCode);
                     String[] parts = token.split("\\.");
                     JSONObject payload = new JSONObject(decode(parts[1]));
                     _log.info(payload.getString("mail"));
                     email = payload.getString("mail");
                 }
              }
         //After success token request login to liferay using the credentials emailAddress,userId and password
          if(Validator.isNotNull(email)) {      
            user =  _userLocalService.getUserByEmailAddress(companyId, email);
            String url = "http://localhost:8081/web/guest/documenturl";
            //String path = PrefsPropsUtil.getString(companyId, PropsKeys.DEFAULT_LANDING_PAGE_PATH);
            httpServletRequest.setAttribute(AUTO_LOGIN_REDIRECT,path);
            
            credentials = new String[] { String.valueOf(user.getUserId()),
                    user.getPassword(),
                    String.valueOf(user.isPasswordEncrypted()) };
           
        }    
            
            return credentials;
            
        } catch (PortalException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception ex) {
            _log.info("no user found");
            ex.printStackTrace();
            return null;
        }
        //return new String[]{email, user.getPassword() , Boolean.TRUE.toString()};
        return null;
    }

    
   
        @Reference
        public void setUserLocalService(UserLocalService userLocalService) {
            this._userLocalService = userLocalService;
        }
        

        @Reference
        private UserLocalService _userLocalService;

 

Kevin Matthews, modified 3 Years ago.

RE: Integrating external Idp (auth server) with Liferay 7.2 using Oauth2.0

Expert Posts: 253 Join Date: 1/25/16 Recent Posts

I Finally figured out the problem. Couple of changes need to do

  1. I had to setup my landing page in the Administration Control /web/guest/login
  2. I had to create two component classes: 
    • a filter component that subclass the BaseFilter class to override the prcessFilter() method
    • Inside my Filter Component my @Activate when startup should call AUth Server
    •  a autologin componnet that subclass the BaseAutologin
    • Inside my Filter Component my @Activate when startup should log user into liferay after getttin user details from the token claims
  3. After implementing and activating those two components that work in tandem i was able login to Liferay user the user info in claims by decoding the token from Authorization server 

Code Sniipet:

@Component(
    immediate = true,
    property = {
             "dispatcher=FORWARD",
             "dispatcher=REQUEST",
             "servlet-context-name=",
             "servlet-filter-name=SSO Oauth2.0 Filter",
             "url-pattern=/c/portal/login",
             "url-pattern=/c/portal/logout"
    },
    service = Filter.class
)
/** Filter Component
*/
public class SSOFilter extends BaseFilter  {
    
     private static final Log LOG = LogFactoryUtil.getLog(AuthenticationSSOFilter.class);
        private FilterAdapter filterAdapter;

 

 @Activate
        @Modified
        protected void activate() {
            LOG.info("**************** SSOFilter Activated ******************");
            filterAdapter = new FilterAdapter(new PortalAdapterImpl(_userLocalService));
        }

 @Override
        protected void processFilter(
                HttpServletRequest request, HttpServletResponse response,
                FilterChain filterChain)
                throws Exception {

                override this methhod by calling processFilter()

}

}

 

/**
 * 
 */
@Component(
         immediate = true,
         service = AutoLogin.class
    )
public class AutoLoginService extends BaseAutoLogin {

 @Activate
        protected void activate() {
            _log.info("**************** AutoLoginService Activated ******************");
            autoLoginAdapter = new AutoLoginAdapter(new PortalAdapterImpl(_userLocalService));
        }

 

 @Override
        protected String[] doLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
            return autoLoginAdapter.doLogin(request, response);
        }

 

}