Allow AWSMobileClient to accept tokens as a starting point
occassionally opened this issue · 6 comments
Which AWS Services is the feature request for?
AWSMobileClient
Cognito.
Is your feature request related to a problem? Please describe.
Using Sign in with Apple as an identity provider is problematic, because unlike other providers, Apple does not provide a client-side method for refreshing tokens and Cognito does not handle it for developers either. See this issue for more details.
To work around this, I've attempted to implement a hybrid approach:
- The user Signs in with Apple in the client.
- The client sends the Apple tokens to the AWS server.
- The AWS server validates the tokens, admin-creates a Cognito User Pool user, confirms the user, and generates Cognito tokens for the user.
This is where the problem arises.
First, the tokens generated server-side are not universal in the sense that they aren't automatically shared with the client. Meaning, if the client then attempts AWSMobileClient.default().getTokens()
, it will throw an error saying the user is not signed in.
Second, if the server returned the tokens to the client, they cannot be passed to AWSMobileClient
.
This means the only solution is likely to not use AWSMobileClient
at all, and manually handle all client-side logic related to signing in, signing out, getting tokens, etc.
Describe the solution you'd like
Add a feature like AWSMobileClient.default().setTokens(idToken, accessToken, refreshToken)
.
This will make it so the server can generate the initial tokens, after which AWSMobileClient
will handle the process as usual.
AWSMobileClient
does not need to do anything regarding Sign in with Apple. It simply needs to accept the Cognito tokens as a starting point, after which its flow remains unchanged.
The client is responsible for detecting if or when Sign in with Apple authorization is revoked, at which point will also revoke the Cognito tokens and require the user to begin the process again.
Describe alternatives you've considered
There are very few alternatives to using Sign in with Apple with Cognito, other than doing everything yourself or switching to another provider like Firebase, which does handle refreshing Apple's tokens for the developer.
Additional context
Sign in with Apple is mandatory in all applications that provide any other identity-provider sign in options. Cognito and AWSMobileClient
do not provide much support for Sign in with Apple other than the bare-bones minimum which is not entirely workable in most cases.
@occassionally I have marked this as a feature request.
You could try using HostedUI which generates and returns the token to AWSMobileClient.
@harsh62 Thanks! Unfortunately, using HostedUI is not really an option due to its appearance. Even with styling options, it's not what most users expect from a production iOS app. Can the token-refreshing logic of HostedUI be replicated in AWSMobileClient? It seems like if HostedUI can do it, AWSMobileClient could too.
token-refreshing logic of HostedUI be replicated in AWSMobileClient
Unfortunately that is not true because HostedUI uses Cognito's internal API to achieve that logic which is not available to AWS SDK. AWSMobileClient is only able to access publicly released Cognito APIs. This has been requested a few times on Github and we forwarded that request to Cognito service team. I would suggest you to open a ticket with AWS support.
For the time being, accepting tokens in not available. You could build it yourself and open a PR. I will be happy to look at it.
Understood, thanks for the clarification.
For the time being, accepting tokens in not available. You could build it yourself and open a PR. I will be happy to look at it.
That might be an option. I'm not too familiar with this library though, so could you please let me know if I'm on the right track with this?
It looks like getTokens()
uses FetchUserPoolTokensOperation
:
Which uses its internal fetchToken()
function:
Specifically, this would be the end result of a successful setTokens()
invocation:
getTokens()
handles two cases: .userPools
and .hostedUI
, otherwise it throws an error. setTokens()
would handle only .userPools
. It would accept a Tokens
object:
aws-sdk-ios/AWSAuthSDK/Sources/AWSMobileClient/Models/Tokens.swift
Lines 20 to 34 in 19ab7d4
And if the federationProvider
is .userPools
, it will call acceptEvent(.tokenFetched(tokens))
.
If that all sounds about right, could you please give me some clarity on these questions:
- Since
getTokens()
is using the Cognito API, it knows the tokens are valid if thecase
is.success
.setTokens()
would be accepting aToken
object that might not have valid tokens. Is there any need forsetTokens()
to do some kind of validation, and if so, are there built-in functions to do that? I imagine the simplest validation would be when the existing infrastructure ofAWSMobileClient
attempts to use the tokens and finds that they're invalid, right? But that may not be acceptable. If it isn't, and validation is necessary, hopefully there's some kind of logic already implemented in the library that could be used. - After
AWSMobileClient
is provided the initial tokens viasetTokens()
, will it handle the token refresh process going forward from that point, as if it had retrieved the tokens itself viagetTokens()
? Or would the developer need to manually handle it and keep callingsetTokens()
periodically? I hope the answer to this is that it will behave normally, until the user signs out; so overall,setTokens()
would only be necessary on each sign in.