All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.dev.programadorthi.routing.auth.AuthenticationContext.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0-alpha02
Show newest version
/*
 * Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
 */

package dev.programadorthi.routing.auth

import dev.programadorthi.routing.core.application.ApplicationCall
import io.ktor.util.AttributeKey
import kotlin.reflect.KClass

/**
 * An authentication context for a call.
 * @param call instance of [ApplicationCall] this context is for.
 */
public class AuthenticationContext(call: ApplicationCall) {
    public var call: ApplicationCall = call
        private set

    private val errors = HashMap()

    internal val combinedPrincipal: CombinedPrincipal = CombinedPrincipal()

    /**
     * All registered errors during auth procedure (only [AuthenticationFailedCause.Error]).
     */
    public val allErrors: List
        get() = errors.values.filterIsInstance()

    /**
     * All authentication failures during auth procedure including missing or invalid credentials.
     */
    public val allFailures: List
        get() = errors.values.toList()

    /**
     * Appends an error to the errors list. Overwrites if already registered for the same [key].
     */
    public fun error(
        key: Any,
        cause: AuthenticationFailedCause,
    ) {
        errors[key] = cause
    }

    /**
     * Gets an [AuthenticationProcedureChallenge] for this context.
     */
    public val challenge: AuthenticationProcedureChallenge = AuthenticationProcedureChallenge()

    /**
     * Sets an authenticated principal for this context.
     */
    public fun principal(principal: Principal) {
        combinedPrincipal.add(null, principal)
    }

    /**
     * Sets an authenticated principal for this context from provider with name [provider].
     */
    public fun principal(
        provider: String? = null,
        principal: Principal,
    ) {
        combinedPrincipal.add(provider, principal)
    }

    /**
     * Retrieves a principal of the type [T] from provider with name [provider], if any.
     */
    public inline fun  principal(provider: String? = null): T? {
        return principal(provider, T::class)
    }

    /**
     * Retrieves a principal of the type [T], if any.
     */
    public fun  principal(
        provider: String?,
        klass: KClass,
    ): T? {
        return combinedPrincipal.get(provider, klass)
    }

    /**
     * Requests a challenge to be sent to the client if none of mechanisms can authenticate a user.
     */
    public fun challenge(
        key: Any,
        cause: AuthenticationFailedCause,
        function: ChallengeFunction,
    ) {
        error(key, cause)
        challenge.register.add(cause to function)
    }

    public companion object {
        private val AttributeKey = AttributeKey("AuthContext")

        internal fun from(call: ApplicationCall): AuthenticationContext {
            val existingContext = call.attributes.getOrNull(AttributeKey)
            if (existingContext != null) {
                existingContext.call = call
                return existingContext
            }
            val context = AuthenticationContext(call)
            call.attributes.put(AttributeKey, context)
            return context
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy