Farid Benhaimoud
07/13/2023, 5:57 PMinstall(Auth) {
bearer {
loadTokens {
BearerTokens(accesToken = "abc123", refreshToken = "xyz111")
}
refreshTokens { // this: RefreshTokensParams
// Refresh tokens and return them as the 'BearerTokens' instance
BearerTokens(accesToken = "def456", refreshToken = "xyz111")
}
}
}
s3rius
07/13/2023, 6:29 PMWhat is the difference between the refreshToken in loadTokens and refreshTokens block?There's no difference. The
loadTokens
returns a token pair loaded from internal storage somewhere. (Or you leave it null if you don't want to use that).
refreshTokens
gives you access to a client
and oldTokens
parameters, and requires you to produce a new token pair with that.
I've initially had some trouble with it too but after some fiddling it works quite well. I can't give you a sample project but this is a somewhat abridged part of my configuration:
_bearer_ *{*
loadTokens *{* tokenStorage.load() *} // simply load existing tokens if available*
refreshTokens *{*
// use the given client to get new tokens (optional)
val response = client.submitForm(
url = "$_baseUrl_/api/oauth/token",
formParameters = Parameters.build *{*
append("grant_type", "refresh_token")
append("client_id", "my client id")
append("refresh_token", oldTokens!!.refreshToken)
*}*,
encodeInQuery = false,
block = *{*
_accept_(ContentType.Application.Json)
}
)
val content = response.body<OAuthResponse>() // TODO: error handling
val tokens = BearerTokens(accessToken = content.token, refreshToken = content.refresh_token)
tokenStorage.store(tokens) // remember tokens (optional)
tokens
}
}
I've omitted error handling and a few other bits.
It works fine on my multiplat setup for Android+Desktop, with the only tokenStorage
being specialized for each platform. But you could use a library like multiplatform-settings to take care of that.Farid Benhaimoud
07/13/2023, 6:31 PMs3rius
07/13/2023, 6:33 PMFarid Benhaimoud
07/13/2023, 6:35 PMs3rius
07/13/2023, 6:36 PMloadTokens {
refreshTokens { ... } <--
...
}
Farid Benhaimoud
07/13/2023, 6:37 PMloadTokens {
BearerTokens(accesToken = "abc123", refreshToken = "xyz111")
}
you see there is a refreshtoken field. 2nd arguments3rius
07/13/2023, 6:39 PMFarid Benhaimoud
07/13/2023, 6:41 PMFarid Benhaimoud
07/13/2023, 8:27 PMFarid Benhaimoud
07/13/2023, 8:35 PMsendWithoutRequest { request ->
//TODO use public or private in your endpoints
request.url.encodedPath.contains("login") || request.url.encodedPath.contains("signup")
}
s3rius
07/13/2023, 8:53 PM// helper functions
val AuthAttributeKey = AttributeKey<Boolean>("WantToAuthorize")
fun HttpRequestBuilder.authorize() = attributes.put(AuthAttributeKey, true)
// configuration
bearer {
...
sendWithoutRequest { it.attributes.getOrNull(OAuth.AuthAttributeKey) == true }
}
// example of how tell Ktor to add authorization:
client.get<String>("some/url") { authorize() }