This document provides detailed information about the authentication and authorization APIs in the Summon library.
Authentication in Summon provides a flexible system for handling user identity verification across different platforms.
The primary class representing an authenticated session.
package code.yousef.summon.security
interface Authentication {
val principal: Principal
val credentials: Credentials
val isAuthenticated: Boolean
val expiresAt: Long?
fun isExpired(): Boolean
}
data class JwtAuthentication(
override val principal: Principal,
override val credentials: JwtCredentials,
override val expiresAt: Long? = null
) : Authentication {
override val isAuthenticated: Boolean = true
override fun isExpired(): Boolean = expiresAt?.let { System.currentTimeMillis() > it } ?: false
}
Interface for authentication providers that handle different types of authentication.
interface AuthenticationProvider {
suspend fun authenticate(credentials: Credentials): AuthenticationResult
suspend fun refresh(authentication: Authentication): AuthenticationResult
suspend fun invalidate(authentication: Authentication)
}
JWT-based authentication provider that works with token-based authentication systems.
class JwtAuthenticationProvider(
private val apiBaseUrl: String,
private val tokenExpiration: Long = 3600L // 1 hour in seconds
) : AuthenticationProvider {
override suspend fun authenticate(credentials: Credentials): AuthenticationResult
override suspend fun refresh(authentication: Authentication): AuthenticationResult
override suspend fun invalidate(authentication: Authentication)
}
Manages the current security context, including authentication state.
object SecurityContext {
fun getAuthentication(): Authentication?
fun setAuthentication(authentication: Authentication?)
fun clearAuthentication()
fun isAuthenticated(): Boolean
fun getPrincipal(): Principal?
fun hasRole(role: Role): Boolean
fun hasPermission(permission: Permission): Boolean
fun <T> withAuthentication(authentication: Authentication?, block: () -> T): T
}
Represents an authenticated user in the system.
interface Principal {
val id: String
val roles: Set<Role>
val permissions: Set<Permission>
val attributes: Map<String, Any>
}
Classes that represent user roles and permissions.
@JvmInline
value class Role(val name: String)
@JvmInline
value class Permission(val name: String)
Summon provides annotations for securing components and routes.
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class RequiresAuthentication
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class RequiresRoles(val roles: Array<String>)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class RequiresPermissions(val permissions: Array<String>)
A component that conditionally renders content based on security requirements.
object SecuredComponent {
@Composable
fun authenticated(content: @Composable () -> Unit)
@Composable
fun unauthenticated(content: @Composable () -> Unit)
@Composable
fun withRole(role: String, content: @Composable () -> Unit)
@Composable
fun withPermission(permission: String, content: @Composable () -> Unit)
}
Configuration for the security system.
data class SecurityConfig(
val authenticationProvider: AuthenticationProvider,
val loginUrl: String = "/login",
val defaultSuccessUrl: String = "/",
val unauthorizedUrl: String = "/unauthorized",
val tokenStorage: TokenStorage = LocalStorageTokenStorage(),
val securityContextHolder: SecurityContextHolder = ThreadLocalSecurityContextHolder()
)
fun securityConfig(init: SecurityConfig.Builder.() -> Unit): SecurityConfig
// Configure security
val securityConfig = securityConfig {
authenticationProvider = JwtAuthenticationProvider(
apiBaseUrl = "https://api.example.com"
)
loginUrl = "/login"
defaultSuccessUrl = "/"
}
// Protected component
@RequiresAuthentication
@Composable
fun UserProfile() {
val user = SecurityContext.getPrincipal()
Text("Welcome, ${user?.attributes?.get("name") ?: "User"}")
}
// Role-based authorization
@RequiresRoles(["admin"])
@Composable
fun AdminPanel() {
// Admin-only content
}
// Using SecuredComponent
@Composable
fun AuthAwareComponent() {
SecuredComponent.authenticated {
Text("You are logged in!")
}
SecuredComponent.unauthenticated {
Text("Please log in to continue")
Button(text = "Login", onClick = { /* handle login */ })
}
SecuredComponent.withRole("admin") {
Text("Admin panel")
}
}