sign_in_with_apple: AuthorizationErrorCode.invalidResponse: No code query parameter set

671 views Asked by At

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?

2

There are 2 answers

3
Zakaria Hossain On

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)

0
user1836985 On

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.