4

I use the latest version of sign_in_with_apple using the following code to allow signing in with Apple to my Flutter app on Android.

final credential = await SignInWithApple.getAppleIDCredential(
  scopes: [
    AppleIDAuthorizationScopes.email,
    AppleIDAuthorizationScopes.fullName,
  ],
  webAuthenticationOptions: WebAuthenticationOptions(
    clientId: '***Service Identifier***',
    redirectUri:
        // For web your redirect URI needs to be the host of the "current page",
        // while for Android you will be using the API server that redirects back into your app via a deep link
        kIsWeb ? Uri.parse('https://${window.location.host}/') : Uri.parse('https://***Backend***/callback'),
  ),
  nonce: nonce,
);

I have taken the code for the backend from the package README.md:

apple_router.post("/callback", (request, response) => {
    console.log(">>> Apple callback received <<<");
    console.log("Body:");
    console.log(request.body);
    console.log("Query:");
    console.log(request.query);
    console.log("Params:");
    console.log(request.params);
    const redirect = `intent://callback?${new URLSearchParams(
        request.body
    ).toString()}#Intent;package=${process.env.ANDROID_PACKAGE_IDENTIFIER
        };scheme=signinwithapple;end`;

    console.log(`Redirecting to ${redirect}`);

    response.redirect(307, redirect);
});

I have also configured everything at Apple with the correct domains, but on my backend, when I log into the app, only an empty request arrives:

>>> Apple callback received <<<
Body:
{}
Query:
{}
Params:
{}
Redirecting to intent://callback?#Intent;package=***Android package ID***;scheme=signinwithapple;end

Which is why it doesn't work properly in the app either:

E/flutter (27962): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: SignInWithAppleAuthorizationError(AuthorizationErrorCode.invalidResponse, parseAuthorizationCredentialAppleIDFromDeeplink: No `code` query parameter set))

I have checked everything several times and I no longer have any idea where this problem could come from. Does anyone have any ideas?

PlutoHDDev
  • 540
  • 7
  • 25

2 Answers2

0

Using this sign_in_with_apple apple will provide you the email, fullName, etc. information only for the first authorizations.

So, you have to take few steps to apple authorization.

Flutter/client side code/mechanism

void loginSignUpWithApple() async {
    SignInWithApple.getAppleIDCredential(
      scopes: [
        AppleIDAuthorizationScopes.email,
        AppleIDAuthorizationScopes.fullName
      ],
    ).then((value) {
      _socialLoginSignUp(value.authorizationCode, describeEnum(LoginMethod.APPLE));
    }).catchError((e) {
      showMessage("Something went wrong: $e", isError: true);
    });
  }

Backend side code/mechanism

  1. Generate JWT using apple key id and private key
  2. Get auth token from apple server by using generated jwt and clint sent authorizationCode then extract the IdToken from the auth token response
  3. Decode the IdToken and get the IdTokenHeader
  4. From the IdTokenHeader get the kId
  5. Using the kId get the list of keys from apple server then extract the actual key
  6. Using the actual key create apple key to public key
  7. Using public key and IdToken get the claims then decode the claim to get the user email
  8. After getting the user email you can store this email in your database or other place and you can trust this is mail as a valid apple mail.

You can see the backend implementation code which is we have implemented previously in java (spring boot).

Sample backend code for apple login (Try with VPN if link is not working)

Zakaria Hossain
  • 2,188
  • 2
  • 13
  • 24
  • I already knew that email and name are only provided for the first authorization. Therefore, I removed my app from my logins in my AppleID (https://appleid.apple.com/) and tried it again - same problem. I know of what you described but I think that it isn't the issue I have. According to your answer, I should somehow be able to sign in (even though my email isn't provided again), but as I have described, the request to the callback URL that comes from Apple after putting in my credentials is completely empty. No tokens or anything else. I don't need to know the email address at that point. – PlutoHDDev Mar 15 '22 at 21:50
  • Removing `AppleIDAuthorizationScopes.email` and `AppleIDAuthorizationScopes.fullName` from the `scopes` does not change anything about the issue. – PlutoHDDev Mar 15 '22 at 21:52
  • @PlutoHDDev, I am having the same problem. Have you solved it? – user1836985 Aug 11 '22 at 22:47
0

I found the problem: if you are using express as your server, add

bodyParser.urlencoded({ extended: true })

as middleware for your callback handler and then request.body will not be empty.

user1836985
  • 61
  • 1
  • 2