-
Notifications
You must be signed in to change notification settings - Fork 768
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Refresh Tokens #5023
Refresh Tokens #5023
Conversation
- Hardcodes refresh_tokens on for the moment - Refresh tokens requested during login - Refresh tokens and access token expiry parsed in login response - Access Token provider synchronises refresh so that we have a leader refresh requests while other requests are blocked and recieve the new access token when the leader succeeds. - Adds refresh wizard to authentication service for unauthed refresh api.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. I've made a few remarks.
matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt
Outdated
Show resolved
Hide resolved
matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt
Outdated
Show resolved
Hide resolved
matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/#/#Wizard.kt
Outdated
Show resolved
Hide resolved
matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/refresh/RefreshWizard.kt
Outdated
Show resolved
Hide resolved
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt
Outdated
Show resolved
Hide resolved
.../src/main/java/org/matrix/android/sdk/internal/network/parsing/CredentialsResponseAdapter.kt
Show resolved
Hide resolved
...src/main/java/org/matrix/android/sdk/internal/network/token/HomeserverAccessTokenProvider.kt
Outdated
Show resolved
Hide resolved
...src/main/java/org/matrix/android/sdk/internal/network/token/HomeserverAccessTokenProvider.kt
Outdated
Show resolved
Hide resolved
...src/main/java/org/matrix/android/sdk/internal/network/token/HomeserverAccessTokenProvider.kt
Outdated
Show resolved
Hide resolved
...src/main/java/org/matrix/android/sdk/internal/network/token/HomeserverAccessTokenProvider.kt
Outdated
Show resolved
Hide resolved
Matrix SDKIntegration Tests Results:
|
…eature/dla/refresh_tokens
…eature/dla/refresh_tokens
…ase. enable refresh tokens.
vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more comments, please let me know what you think.
Sorry this is a very sensitive subject, I want to be sure that there is no issue and the implementation is crystal clear.
...x-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/#/DefaultLoginWizard.kt
Outdated
Show resolved
Hide resolved
matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt
Outdated
Show resolved
Hide resolved
matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/RefreshResult.kt
Outdated
Show resolved
Hide resolved
return responseCredentials | ||
} | ||
// We have received a credential response from the server, estimate the expiry datetime. | ||
return responseCredentials.copy(expiryTs = System.currentTimeMillis() + responseCredentials.expiresInMs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand reading this code again that expiryTs
does not come from the server, do it?
This a bit weird to create a customized Json adapter to handle this.
Not sure how to implement it in another way, I will think more about it.
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt
Show resolved
Hide resolved
...rc/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAccessTokenProvider.kt
Outdated
Show resolved
Hide resolved
...sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityModule.kt
Outdated
Show resolved
Hide resolved
vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt
Show resolved
Hide resolved
…eature/dla/refresh_tokens
Ktlint Results👎 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more remarks.
@ganfra can you have a quick look on this PR please? especially the refresh token management itself.
...x-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/#/DefaultLoginWizard.kt
Show resolved
Hide resolved
@Unauthenticated okHttpClient: Lazy<OkHttpClient>, | ||
retrofitFactory: RetrofitFactory, | ||
homeServerConnectionConfig: HomeServerConnectionConfig | ||
): AuthAPI { | ||
): RefreshTokenAPI { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you have retrofit: Retrofit
as the only parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The okHttpClient
here is unauthenticated. Would I have to provide another unauthenticated version of Retrofit
? is there any example of where we do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it a problem to send the current (and outdated) access token in the request header to refresh the token?
I think this is not a problem. (but I have done no test)
To me, it should even be mandatory server side to provide the previous access token to be able to get a new token.
If this is not a problem, I would remove this change on the SessionModule
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well according to the spec
This new API should be rate-limited and does not require authentication since only the refresh_token parameter is needed.
So it's not needed but I don't imagine the access token itself would cause a problem.
However the authenticated requests(which /refresh
would bcome) run through the AccessTokenInterceptor and HomeserverAccessTokenProvider
which is itself making the request to refresh. I think you might have to add additional defensive code there to check that the current request is not /refresh
. Seems a more sensible design to keep the /refresh
endpoint outside of that code flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your (good) point about potential endless loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah you can keep it like that it's ok
…eature/dla/refresh_tokens
import com.squareup.moshi.JsonClass | ||
|
||
@JsonClass(generateAdapter = true) | ||
data class RefreshResult( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be internal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts
*/ | ||
fun getLoginWizard(): LoginWizard | ||
fun getLoginWizard(enableRefreshTokenAuth: Boolean = false): LoginWizard |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this flag enabled on MatrixConfiguration instead? It would avoid passing this everywhere and directly be injected in the few places where it makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually had it that way initially. @bmarty felt it would be better to be a more explicit part of the api on the AuthenticationService
vs a config people might not know about. I don't really have a strong opinion on it. :)
@Unauthenticated okHttpClient: Lazy<OkHttpClient>, | ||
retrofitFactory: RetrofitFactory, | ||
homeServerConnectionConfig: HomeServerConnectionConfig | ||
): AuthAPI { | ||
): RefreshTokenAPI { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah you can keep it like that it's ok
private val sessionParamsStore: SessionParamsStore | ||
private val sessionParamsStore: SessionParamsStore, | ||
private val refreshTokenTask: RefreshTokenTask, | ||
private val globalErrorReceiver: GlobalErrorReceiver | ||
) : AccessTokenProvider { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okhttp has an API to handle accessToken and refreshToken when needed, might be the opportunity to use it instead of a custom interceptor/provider ?
See this article: https://www.lordcodes.com/articles/authorization-of-web-requests-for-okhttp-and-retrofit for example
Will have to be done again, if we want to support this using https://www.lordcodes.com/articles/authorization-of-web-requests-for-okhttp-and-retrofit. I guess this is probably better to create another PR. |
Resolves #4943
What's in the PR
UNKOWN_TOKEN
from the server(the source of truth on token validity).#TODO
LoginMode
isSSOAndPassword
results in an empty space where a login UI component should be displayed. #5192