-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#3 ports code from AtlasOfLivingAustralia/ala-cas-2.0, updates JNDI f…
…or running in boot repackage configuration
- Loading branch information
1 parent
13f006a
commit c7b0e2b
Showing
21 changed files
with
591 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package au.org.ala.cas | ||
|
||
import org.apereo.cas.configuration.model.core.authentication.PasswordEncoderProperties | ||
import org.apereo.cas.configuration.model.support.cookie.CookieProperties | ||
import org.apereo.cas.configuration.model.support.jpa.AbstractJpaProperties | ||
import org.springframework.boot.context.properties.ConfigurationProperties | ||
|
||
@ConfigurationProperties(value = "ala") | ||
open class AlaCasProperties( | ||
var cookie: CookieProperties = CookieProperties(), | ||
var userCreator: UserCreatorProperties = UserCreatorProperties() | ||
) | ||
|
||
open class UserCreatorProperties( | ||
var passwordEncoder: PasswordEncoderProperties = PasswordEncoderProperties(), | ||
var jdbc: JDBCUserCreatorProperties = UserCreatorProperties.JDBCUserCreatorProperties(), | ||
var userCreatePassword: String = "" | ||
) { | ||
open class JDBCUserCreatorProperties : AbstractJpaProperties() { | ||
var createUserProcedure: String = "sp_create_user" | ||
} | ||
|
||
} | ||
|
40 changes: 40 additions & 0 deletions
40
src/main/kotlin/au/org/ala/cas/delegated/AlaPac4jAuthenticationConfiguration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package au.org.ala.cas.delegated; | ||
|
||
import au.org.ala.cas.delegated.UserCreator | ||
import au.org.ala.cas.delegated.UserCreatorALA | ||
import au.org.ala.cas.AlaCasProperties | ||
import au.org.ala.utils.logger | ||
import org.apereo.cas.authentication.principal.PrincipalFactory | ||
import org.apereo.cas.authentication.principal.PrincipalResolver | ||
import org.apereo.cas.configuration.support.Beans | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
|
||
@Configuration | ||
@EnableConfigurationProperties(AlaCasProperties::class) | ||
open class AlaPac4jAuthenticationConfiguration { | ||
|
||
companion object { | ||
private val logger = logger<AlaPac4jAuthenticationConfiguration>() | ||
} | ||
|
||
@Autowired | ||
lateinit var alaCasProperties: AlaCasProperties | ||
|
||
@Bean | ||
open fun userCreator(): UserCreator = UserCreatorALA().apply { | ||
logger.debug("Creating UserCreatorALA with {}, {}, {}, {}", alaCasProperties.userCreator.jdbc.dataSourceName, alaCasProperties.userCreator.userCreatePassword, alaCasProperties.userCreator.jdbc.createUserProcedure) | ||
dataSource = Beans.newDataSource(alaCasProperties.userCreator.jdbc) | ||
passwordEncoder = Beans.newPasswordEncoder(alaCasProperties.userCreator.passwordEncoder) | ||
userCreatePassword = alaCasProperties.userCreator.userCreatePassword | ||
createUserProcedure = alaCasProperties.userCreator.jdbc.createUserProcedure | ||
} | ||
|
||
@Bean(name = arrayOf("clientPrincipalFactory")) | ||
open fun clientPrincipalFactory( | ||
@Autowired personDirectoryPrincipalResolver: PrincipalResolver, | ||
@Autowired userCreator: UserCreator | ||
): PrincipalFactory = AlaPrincipalFactory(personDirectoryPrincipalResolver, userCreator) | ||
} |
88 changes: 88 additions & 0 deletions
88
src/main/kotlin/au/org/ala/cas/delegated/AlaPrincipalFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package au.org.ala.cas.delegated | ||
|
||
import au.org.ala.cas.delegated.UserCreator | ||
import au.org.ala.utils.logger | ||
import org.apache.commons.lang3.builder.HashCodeBuilder | ||
import org.apereo.cas.authentication.Credential | ||
import org.apereo.cas.authentication.principal.Principal | ||
import org.apereo.cas.authentication.principal.PrincipalFactory | ||
import org.apereo.cas.authentication.principal.PrincipalResolver | ||
import javax.security.auth.login.FailedLoginException | ||
|
||
class AlaPrincipalFactory(private val principalResolver: PrincipalResolver, | ||
val userCreator: UserCreator): PrincipalFactory { | ||
|
||
companion object { | ||
private const val serialVersionUID: Long = -3999695695604948495L | ||
private val logger = logger<AlaPrincipalFactory>() | ||
val EMAIL_PATTERN = Regex("^.+@.+\\..+$") | ||
} | ||
|
||
override fun createPrincipal(id: String) = createAlaPrincipal(id, emptyMap()) | ||
|
||
override fun createPrincipal(id: String, attributes: Map<String, Any>) = createAlaPrincipal(id, attributes) | ||
|
||
private fun createAlaPrincipal(id: String, attributes: Map<String, Any>): Principal { | ||
val attributeParser = AttributeParser.create(id, attributes) | ||
val email = attributeParser.findEmail() | ||
logger.debug("email : {}", email) | ||
|
||
if (email == null || !EMAIL_PATTERN.matches(email)) { | ||
logger.debug("Invalid email : {}, authentication aborted!", email) | ||
throw FailedLoginException("No email address found in $email; email address is required to lookup (and/or create) ALA user!") | ||
} | ||
|
||
//NOTE: just in case social media gave us email containing Upper case letters | ||
val emailAddress = email.toLowerCase() | ||
val alaCredential = Credential() { -> emailAddress } // SAM conversion | ||
|
||
// get the ALA user attributes from the userdetails DB ("userid", "firstname", "lastname", "authority") | ||
var principal = principalResolver.resolve(alaCredential) | ||
logger.debug("{} resolved principal: {}", principalResolver, principal) | ||
|
||
// does the ALA user exist? | ||
if (!validatePrincipalALA(principal)) { | ||
// create a new ALA user in the userdetails DB | ||
logger.debug("user {} not found in ALA userdetails DB, creating new ALA user for: {}.", emailAddress, emailAddress) | ||
|
||
val firstName = attributeParser.findFirstname() | ||
val lastName = attributeParser.findLastname() | ||
|
||
if (firstName != null && lastName != null) { | ||
// if no userId parameter is returned then no db entry was created | ||
val userId = userCreator.createUser(emailAddress, firstName, lastName) ?: throw FailedLoginException("Unable to create user for $emailAddress, $firstName, $lastName") | ||
logger.debug("Received new user id $userId") | ||
|
||
// re-try (we have to retry, because that is how we get the required "userid") | ||
principal = principalResolver.resolve(alaCredential) | ||
|
||
logger.debug("{} resolved principal: {}", principalResolver, principal) | ||
} else { | ||
logger.warn("Couldn't extract firstname or lastname for {} from attributes", id, attributes) | ||
} | ||
|
||
if (!validatePrincipalALA(principal)) { | ||
// we failed to lookup ALA user (most likely because the creation above failed), complain, throw exception, etc. | ||
throw FailedLoginException("Unable to create ALA user for $emailAddress with attributes $attributes") | ||
} | ||
} | ||
return principal | ||
} | ||
|
||
internal fun validatePrincipalALA(principal: Principal?) = principal != null && principal.attributes != null && principal.attributes.containsKey("userid") | ||
|
||
|
||
override fun equals(other: Any?): Boolean { | ||
if (other == null) { | ||
return false | ||
} | ||
if (other === this) { | ||
return true | ||
} | ||
return other.javaClass == javaClass | ||
} | ||
|
||
override fun hashCode(): Int { | ||
return HashCodeBuilder(13, 37).toHashCode() | ||
} | ||
} |
Oops, something went wrong.