Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pac4j 6 upgrade #47

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: groovy
sudo: false
jdk:
- openjdk11
- openjdk17
branches:
only:
- master
Expand Down
8 changes: 7 additions & 1 deletion ala-auth/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ apply plugin: 'maven-publish'
group 'org.grails.plugins'

repositories {
mavenLocal()
maven { url "https://nexus.ala.org.au/content/groups/public/" }
maven { url "https://repo.grails.org/grails/core" }
mavenCentral()
mavenLocal()
}

configurations {
Expand All @@ -38,6 +38,12 @@ configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

//dependencyManagement {
// imports {
// mavenBom "org.grails:grails-bom:$grailsVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import com.nimbusds.oauth2.sdk.token.BearerAccessToken
import com.nimbusds.oauth2.sdk.util.JSONObjectUtils
import net.minidev.json.JSONObject
import net.minidev.json.parser.ParseException
import org.pac4j.core.adapter.FrameworkAdapter
import org.pac4j.core.config.Config
import org.pac4j.core.context.WebContextFactory
import org.pac4j.core.context.session.SessionStore
import org.pac4j.core.context.session.SessionStoreFactory
import org.pac4j.core.profile.factory.ProfileManagerFactory
import org.pac4j.core.util.FindBest
import org.pac4j.jee.config.AbstractConfigFilter
import org.pac4j.jee.context.JEEContextFactory
import org.pac4j.jee.context.session.JEESessionStore
import org.pac4j.jee.context.JEEFrameworkParameters
import org.pac4j.oidc.profile.OidcProfile

import javax.servlet.FilterChain
Expand All @@ -27,16 +27,16 @@ import javax.servlet.http.HttpServletResponse
class AffiliationSurveyFilter extends AbstractConfigFilter {

WebContextFactory webContextFactory
SessionStore sessionStore
SessionStoreFactory sessionStoreFactory
ProfileManagerFactory profileManagerFactory

final Set<String> requiredScopesForAffiliationCheck// = ['ala', 'ala/attrs']
final String affiliationAttribute// = 'affiliation'
final String countryAttribute

AffiliationSurveyFilter(Config config, SessionStore sessionStore, WebContextFactory webContextFactory, Set<String> requiredScopesForAffiliationCheck, String affiliationAttribute, String countryAttribute) {
AffiliationSurveyFilter(Config config, SessionStoreFactory sessionStoreFactory, WebContextFactory webContextFactory, Set<String> requiredScopesForAffiliationCheck, String affiliationAttribute, String countryAttribute) {
this.config = config
this.sessionStore = sessionStore
this.sessionStoreFactory = sessionStoreFactory
this.webContextFactory = webContextFactory
this.requiredScopesForAffiliationCheck = requiredScopesForAffiliationCheck
this.affiliationAttribute = affiliationAttribute
Expand All @@ -45,9 +45,12 @@ class AffiliationSurveyFilter extends AbstractConfigFilter {

@Override
protected void internalFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
def webContext = FindBest.webContextFactory(this.webContextFactory, config, JEEContextFactory.INSTANCE).newContext(request, response)
def sessionStore = FindBest.sessionStore(this.sessionStore, config, JEESessionStore.INSTANCE)
def profileManager = FindBest.profileManagerFactory(this.profileManagerFactory, config, ProfileManagerFactory.DEFAULT).apply(webContext, sessionStore)
FrameworkAdapter.INSTANCE.applyDefaultSettingsIfUndefined(config)

def params = new JEEFrameworkParameters(request, response)
def webContext = (this.webContextFactory ?: config.getWebContextFactory()).newContext(params)
def sessionStore = (this.sessionStoreFactory ?: config.getSessionStoreFactory()).newSessionStore(params)
def profileManager = (this.profileManagerFactory ?: config.getProfileManagerFactory()).apply(webContext, sessionStore)
profileManager.setConfig(config)

profileManager.getProfile().ifPresent {profile ->
Expand Down
6 changes: 3 additions & 3 deletions ala-auth/src/main/groovy/au/org/ala/web/CookieMatcher.groovy
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package au.org.ala.web

import org.pac4j.core.context.WebContext
import org.pac4j.core.context.session.SessionStore
import org.pac4j.core.context.CallContext
import org.pac4j.core.matching.matcher.Matcher

class CookieMatcher implements Matcher {
Expand All @@ -15,7 +14,8 @@ class CookieMatcher implements Matcher {
}

@Override
boolean matches(WebContext context, SessionStore sessionStore) {
boolean matches(CallContext ctx) {
var context = ctx.webContext()
return context.getRequestCookies().find { it.name == cookieName }?.value?.matches(cookiePattern) ?: false
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package au.org.ala.web

import org.grails.web.util.WebUtils
import org.pac4j.core.adapter.FrameworkAdapter
import org.pac4j.core.config.Config
import org.pac4j.core.context.FrameworkParameters
import org.pac4j.core.context.WebContext
import org.pac4j.core.util.FindBest
import org.pac4j.jee.context.JEEContextFactory
import org.pac4j.jee.context.JEEFrameworkParameters

/**
* Pac4jContextProvider that uses static Grails methods to get at the request and response.
* @deprecated This interface is deprecated and will be removed in a future version.
*/
@Deprecated
class GrailsPac4jContextProvider implements Pac4jContextProvider {

Config config
Expand All @@ -18,10 +22,15 @@ class GrailsPac4jContextProvider implements Pac4jContextProvider {

@Override
WebContext webContext() {
final WebContext context = config.getWebContextFactory().newContext(frameworkParameters())
return context
}

FrameworkParameters frameworkParameters() {
FrameworkAdapter.INSTANCE.applyDefaultSettingsIfUndefined(config)
def gwr = WebUtils.retrieveGrailsWebRequest()
def request = gwr.request
def response = gwr.response
final WebContext context = FindBest.webContextFactory(null, config, JEEContextFactory.INSTANCE).newContext(request, response)
return context
return new JEEFrameworkParameters(request, response)
}
}
7 changes: 4 additions & 3 deletions ala-auth/src/main/groovy/au/org/ala/web/NotBotMatcher.groovy
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package au.org.ala.web

import org.pac4j.core.context.WebContext
import org.pac4j.core.context.session.SessionStore
import org.pac4j.core.context.CallContext
import org.pac4j.core.matching.matcher.Matcher

/**
Expand All @@ -17,7 +16,9 @@ class NotBotMatcher implements Matcher {
}

@Override
boolean matches(WebContext context, SessionStore sessionStore) {
boolean matches(CallContext ctx) {
var context = ctx.webContext()

def headerValue = context.getRequestHeader("User-Agent")
def header = headerValue.orElseGet { "" }
return !filterService.isFiltered(header)
Expand Down
21 changes: 15 additions & 6 deletions ala-auth/src/main/groovy/au/org/ala/web/Pac4jAuthService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromString
import org.pac4j.core.config.Config
import org.pac4j.core.context.session.SessionStore
import org.pac4j.core.context.session.SessionStoreFactory
import org.pac4j.core.profile.ProfileManager
import org.pac4j.core.profile.UserProfile
import org.pac4j.jee.context.JEEContext
import org.pac4j.jee.context.JEEFrameworkParameters

class Pac4jAuthService implements IAuthService {

Expand Down Expand Up @@ -39,7 +42,8 @@ class Pac4jAuthService implements IAuthService {

private final Pac4jContextProvider pac4jContextProvider

private final SessionStore sessionStore
// TODO remove this?
private final SessionStoreFactory sessionStoreFactory

private final LinkGenerator grailsLinkGenerator

Expand All @@ -49,21 +53,26 @@ class Pac4jAuthService implements IAuthService {

private final String displayNameClaim

Pac4jAuthService(Config config, Pac4jContextProvider pac4jContextProvider, SessionStore sessionStore, LinkGenerator grailsLinkGenerator, String alaUseridClaim, String userNameClaim, String displayNameClaim) {
Pac4jAuthService(Config config, Pac4jContextProvider pac4jContextProvider, SessionStoreFactory sessionStoreFactory, LinkGenerator grailsLinkGenerator, String alaUseridClaim, String userNameClaim, String displayNameClaim) {
this.config = config
this.pac4jContextProvider = pac4jContextProvider
this.sessionStore = sessionStore
this.sessionStoreFactory = sessionStoreFactory
this.grailsLinkGenerator = grailsLinkGenerator
this.alaUseridClaim = alaUseridClaim
this.userNameClaim = userNameClaim
this.displayNameClaim = displayNameClaim
}

ProfileManager getProfileManager() {
// TODO This should probably use the call context or something...
def context = pac4jContextProvider.webContext()
final ProfileManager manager = new ProfileManager(context, sessionStore)
manager.config = config
return manager
if (context instanceof JEEContext) {
final ProfileManager manager = config.profileManagerFactory.apply(context, sessionStoreFactory.newSessionStore(new JEEFrameworkParameters(context.nativeRequest, context.nativeResponse)))
manager.config = config
return manager
} else {
throw new IllegalStateException("Pac4jAuthService currently requires a JEEContext")
}
}

UserProfile getUserProfile() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package au.org.ala.web

import org.pac4j.core.context.FrameworkParameters
import org.pac4j.core.context.WebContext

/**
* Provides a Pac4j Context via static methods or similar so that the client code need not take them as params.
*
* @deprecated This interface is deprecated and will be removed in a future version.
*/
@Deprecated
interface Pac4jContextProvider {

WebContext webContext()

FrameworkParameters frameworkParameters()

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package au.org.ala.web

import org.pac4j.core.adapter.FrameworkAdapter
import org.pac4j.core.config.Config
import org.pac4j.core.context.WebContextFactory
import org.pac4j.core.context.session.SessionStore
import org.pac4j.core.context.session.SessionStoreFactory
import org.pac4j.core.profile.factory.ProfileManagerFactory
import org.pac4j.core.util.FindBest
import org.pac4j.jee.config.AbstractConfigFilter
import org.pac4j.jee.context.JEEContextFactory
import org.pac4j.jee.context.session.JEESessionStore
import org.pac4j.jee.context.JEEFrameworkParameters
import org.pac4j.jee.util.Pac4JHttpServletRequestWrapper
import org.springframework.web.util.WebUtils

Expand All @@ -24,20 +24,23 @@ import javax.servlet.http.HttpServletResponse
class Pac4jHttpServletRequestWrapperFilter extends AbstractConfigFilter {

WebContextFactory webContextFactory
SessionStore sessionStore
SessionStoreFactory sessionStoreFactory
ProfileManagerFactory profileManagerFactory

Pac4jHttpServletRequestWrapperFilter(Config config, SessionStore sessionStore, WebContextFactory webContextFactory) {
Pac4jHttpServletRequestWrapperFilter(Config config, SessionStoreFactory sessionStoreFactory, WebContextFactory webContextFactory) {
this.config = config
this.sessionStore = sessionStore
this.sessionStoreFactory = sessionStoreFactory
this.webContextFactory = webContextFactory
}

@Override
protected void internalFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
def webContext = FindBest.webContextFactory(this.webContextFactory, config, JEEContextFactory.INSTANCE).newContext(request, response)
def sessionStore = FindBest.sessionStore(this.sessionStore, config, JEESessionStore.INSTANCE)
def profileManager = FindBest.profileManagerFactory(this.profileManagerFactory, config, ProfileManagerFactory.DEFAULT).apply(webContext, sessionStore)
FrameworkAdapter.INSTANCE.applyDefaultSettingsIfUndefined(config)

def params = new JEEFrameworkParameters(request, response)
def webContext = (this.webContextFactory ?: config.getWebContextFactory()).newContext(params)
def sessionStore = (this.sessionStoreFactory ?: config.getSessionStoreFactory()).newSessionStore(params)
def profileManager = (this.profileManagerFactory ?: config.getProfileManagerFactory()).apply(webContext, sessionStore)
profileManager.setConfig(config)

def existing = WebUtils.getNativeRequest(request, Pac4JHttpServletRequestWrapper)
Expand Down
26 changes: 17 additions & 9 deletions ala-auth/src/main/groovy/au/org/ala/web/Pac4jSSOStrategy.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import org.pac4j.core.context.session.SessionStore
import org.pac4j.core.engine.DefaultSecurityLogic
import org.pac4j.core.engine.SecurityLogic
import org.pac4j.core.http.adapter.HttpActionAdapter
import org.pac4j.core.util.FindBest
import org.pac4j.jee.context.JEEContextFactory
import org.pac4j.jee.context.session.JEESessionStore
import org.pac4j.jee.http.adapter.JEEHttpActionAdapter
import org.pac4j.jee.context.JEEFrameworkParameters
import org.pac4j.jee.util.Pac4JHttpServletRequestWrapper

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
Expand Down Expand Up @@ -47,22 +46,31 @@ class Pac4jSSOStrategy implements SSOStrategy {
@Override
boolean authenticate(HttpServletRequest request, HttpServletResponse response, boolean gateway, String redirectUri) {

final SessionStore bestSessionStore = FindBest.sessionStore(null, config, JEESessionStore.INSTANCE)
final HttpActionAdapter bestAdapter = FindBest.httpActionAdapter(null, config, JEEHttpActionAdapter.INSTANCE)
final SecurityLogic bestLogic = FindBest.securityLogic(securityLogic, config, DefaultSecurityLogic.INSTANCE)
def params = new JEEFrameworkParameters(request, response)
// final SessionStore bestSessionStore = config.getSessionStoreFactory().newSessionStore(params)
// final HttpActionAdapter bestAdapter = config.httpActionAdapter
final SecurityLogic bestLogic = this.securityLogic ?: config.securityLogic

// this is a hack to set the redirectUri in the request so that the OverrideSavedRequestHandler uses it
// on the return redirect
if (bestLogic instanceof DefaultSecurityLogic && bestLogic.savedRequestHandler instanceof OverrideSavedRequestHandler) {
request.setAttribute(OverrideSavedRequestHandler.OVERRIDE_REQUESTED_URL_ATTRIBUTE, redirectUri)
}

final WebContext context = FindBest.webContextFactory(null, config, JEEContextFactory.INSTANCE).newContext(request, response)
final WebContext context = config.webContextFactory.newContext(params)

def result = false

bestLogic.perform(context, bestSessionStore, config, { ctx, session, profiles, parameters ->
// config.getSecurityLogic().perform(config, (ctx, session, profiles) -> {
// // if no profiles are loaded, pac4j is not concerned with this request
// filterChain.doFilter(profiles.isEmpty() ? request : new Pac4JHttpServletRequestWrapper(request, profiles), response);
// return null;
// }, clients, authorizers, matchers, new JEEFrameworkParameters(request, response));

bestLogic.perform(config, { ctx, session, profiles ->
// if no profiles are loaded, pac4j is not concerned with this request
result = true
}, bestAdapter, gateway ? gatewayClients : clients, gateway ? gatewayAuthorizers : authorizers, matchers);
}, gateway ? gatewayClients : clients, gateway ? gatewayAuthorizers : authorizers, matchers, params)
return result
}

Expand Down
Loading