I am trying to implement Sign in with Apple functionality in my Ionic app. In order to do that I am using the plugin: https://github.com/capacitor-community/apple-sign-in
Everything is fine when using it on a device, but I can't make it work as a web app. This is how I start the flow:
SignInWithApple.authorize({
clientId: environment.appId+'.webapp',
redirectURI: 'https://api.xxxx.hu/signInWithAppleCallback',
scopes: 'email name',
state: '12345',
//nonce: 'nonce',
}).then(appleUser => {
this.sendOauthConnectRequest(OauthProvider.apple, appleUser.response.identityToken).subscribe();
}).catch(() => {
this.oauthLoading[oauthProvider] = false;
return;
});
clientId is what I registered with apple and the redirect url is OK as well. When I start this call a new window pops up where I am able to log in with my apple ID, but after finishing it, it won't redirect me to the specified URL. As a matter of fact, nothing happens. No errors in the console either. I can see that there is a successful request to "https://appleid.apple.com/appleauth/auth/oauth/authorize", and in the response I can see all the correct authentication data, simply the redirection is not happening. If I close the login window after that, the callback for the error handler is correctly called, thus notifying me, that the login was not successful (which is what is. expected, since the user closed the window). So any idea on why the redirection is not happening? Thanks a lot!
FYI, this is the solution that I went with. Basically, first part of it is to just separate the web platform from the real devices.
if (Capacitor.getPlatform() === 'web') {
this.appleSignInAbortController = new AbortController();
this.appleSignInWindow = window.open(
'https://appleid.apple.com/auth/authorize?' +
'client_id=com.company.exampleApp&'+
'redirect_uri='+environment.appUrl+'&' +
'response_type=code id_token&' +
'scope=name email&' +
'response_mode=web_message',
'_blank'
);
window.addEventListener(
'message',
(e) => {this.appleTokenReceived(e);},
{signal: this.appleSignInAbortController.signal}
);
return;
}
//Continue with regular sign in on real devices, just like in the original post
appleTokenReceived is a function that gets called with the response from Apple. Please note that the response will also be posted to the specified redirect_uri, but this will happen in the background, server-to-server, so you can't really use it to redirect your client (unless you open up a websocket to your server, but this seems an overkill for this task). So the other half of the code:
async appleTokenReceived(event) {
this.appleSignInAbortController.abort();
this.appleSignInWindow.close();
if (!(event instanceof MessageEvent)) {
return;
}
const data = JSON.parse(event.data);
if (typeof data !== 'object' || data === null) {
return;
}
if (data.data.hasOwnProperty('error')) {
return;
}
let postData: any = {
token: data.data.authorization.id_token,
device_id: 'device UUID',
};
if (
data.data.hasOwnProperty('user') &&
data.data.user.hasOwnProperty('name') &&
data.data.user.name.hasOwnProperty('firstName') &&
data.data.user.name.hasOwnProperty('lastName')
) {
//this is only filled after the first login of the user
postData.name = data.data.user.name.lastName + ' ' + data.data.user.name.firstName;
}
this.http.post(environment.apiUrl + '/api/auth/loginWithApple', postData).subscribe(//Do whatever you need with the data);
}