OAuth authentication
OAuth defines a mechanism for authentication using external providers like Google or Facebook safely.You can read more about OAuth.Ktor has a feature to work with OAuth 1a and 2.0
A simplified OAuth 2.0 workflow:
- The client is redirected to an authorize URL for the specified provider (Google, Facebook, Twitter, Github…).specifying the
clientId
and a valid redirection URL. - Once the login is correct, the provider generates an auth token using a
clientSecret
associated with thatclientId
. - Then the client is redirected to a valid, previously agreed upon, application URL with an auth token that is signed with the
clientSecret
. - Ktor’s OAuth feature verifies the token and generates a Principal
OAuthAccessTokenResponse
. - With the auth token, you can request, for example, the user’s email or id depending on the provider.
Example:
AuthSample.kt
@Location("/login/{type?}") class login(val type: String = "")
val loginProviders = listOf(
OAuthServerSettings.OAuth2ServerSettings(
name = "github",
authorizeUrl = "https://github.com/login/oauth/authorize",
accessTokenUrl = "https://github.com/login/oauth/access_token",
clientId = "***",
clientSecret = "***"
)
).associateBy {it.name}
install(Authentication) {
oauth("gitHubOAuth") {
client = HttpClient(Apache)
providerLookup = { loginProviders[application.locations.resolve<login>(login::class, this).type] }
urlProvider = { url(login(it.name)) }
}
}
routing {
authenticate("gitHubOAuth") {
location<login>() {
param("error") {
handle {
call.loginFailedPage(call.parameters.getAll("error").orEmpty())
}
}
handle {
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
if (principal != null) {
call.loggedInSuccessResponse(principal)
} else {
call.loginPage()
}
}
}
}
}
Depending on the OAuth version, you will get a different Principal
sealed class OAuthAccessTokenResponse : Principal {
data class OAuth1a(
val token: String, val tokenSecret: String,
val extraParameters: Parameters = Parameters.Empty
) : OAuthAccessTokenResponse()
data class OAuth2(
val accessToken: String, val tokenType: String,
val expiresIn: Long, val refreshToken: String?,
val extraParameters: Parameters = Parameters.Empty
) : OAuthAccessTokenResponse()
}