ktorio / ktor

Framework for quickly creating connected applications in Kotlin with minimal effort
https://ktor.io
Apache License 2.0
12.95k stars 1.06k forks source link

Update LDAP Auth to return generic Principal #376

Open maarek opened 6 years ago

maarek commented 6 years ago

LDAP Auth functions could be updated to return a generic Principal variant instead of UserIdPrincipal so that custom Principals could be returned from the builder functions and not require the expanded ldapAuthenticate(K, String, (MutableMap<String, Any?>) -> Unit, InitialDirContext.(K) -> P?): P?

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity.

oleg-larshin commented 4 years ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

QuinnBast commented 2 months ago

Yes please! I need to return custom LDAP user attributes from the ldapAuthenticate method. I was a bit surprised I could only return their name...

Also, consider adding this function, ldapSearch so that you can perform searches for ldap user roles. I had to create this method myself, but luckilly all of these imports are in the standard library:

fun ldapSearch(
    credential: UserPasswordCredential,
    ldapServerURL: String,
    baseDN: String,
    filter: String,
    attributes: Array<String>
): NamingEnumeration<SearchResult> {
    val env = Hashtable<String, String>()
    env[Context.INITIAL_CONTEXT_FACTORY] = "com.sun.jndi.ldap.LdapCtxFactory"
    env[Context.PROVIDER_URL] = ldapServerURL
    env[Context.SECURITY_AUTHENTICATION] = "simple"
    env[Context.SECURITY_PRINCIPAL] = "cn=${credential.name},dc=myOrg,dc=com" // May need to change this. it's hard coded.
    env[Context.SECURITY_CREDENTIALS] = credential.password

    val context = InitialDirContext(env)

    val controls = SearchControls()
    controls.searchScope = SearchControls.SUBTREE_SCOPE
    controls.returningAttributes = attributes

    return context.search(baseDN, filter, controls)
}

I use it like this:

val searchResults = ldapSearch(bindAdmin, "ldap://0.0.0.0:389", "ou=Employees,dc=myOrg,dc=com", "(cn=${credentials.name})", arrayOf("cn", "sn", "mail")).toList()

val userRoles = ldapSearch(bindAdmin, "ldap://0.0.0.0:389", "ou=Roles,dc=myOrg,dc=com",   "(roleOccupant=cn=${credentials.name},ou=Employees,dc=myOrg,dc=com)", arrayOf("cn")).toList()

But unfortunately I can't return any of this information because only UserIdPrincipal is allowed to be returned...

Edit: found a bit of a hacky way around this:

basic("ldap") {
  validate { credentials ->
     var ldapUserSession: SomeCustomClassExtendingPrincipal? = null

    ldapAuthenticate() { /* Set the ldapUserSession in here */ }

   return ldapUserSession