Signin with apple with passport-apple library not returning id_token in nestjs

537 Views Asked by At

I am setting up Apple Login with the "passport-apple" library using NestJS. The first login returns a data object with "state," "code," and "user," but no id_token.

Subsequent logins return data objects containing only "state" and "code."

I understand that Apple does not return a user object in the subsequent login, but "code" and "state" are not unique to the user as the value returned for "state" and "code" is different at any login request. Now there is no way for me to identify the user each time the user makes a login request with Apple.

below is my strategy configuration:

import { Inject, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-apple';

import { readFileSync } from 'fs';

@Injectable()
export class AppleStrategy extends PassportStrategy(Strategy, 'apple') {
  constructor(configService: ConfigService) {
    super({
      clientID: configService.get<string>('APPLE_CLIENT_ID'),
      teamID: configService.get<string>('APPLE_TEAM_ID'),
      keyID: configService.get<string>('APPLE_KEY_ID'),
      key: readFileSync(
        __dirname + '/../../../apple_secret/apple_secret_key.p8',
      ),
      callbackURL: configService.get<string>('APPLE_CALLBACK_URL'),
      passReqToCallback: false,
      response_type: 'code id_token',
      scope: ['name', 'email'],
    });
  }

}

My first login response body:

{
"state": ".......",
"code": "..............................................",
"user": "{"name":{"firstName":"First_Name","lastName":"Last_Name"},"email":"Email"}"
}

My subsequent respnse body:

{
"state": ".......",
"code": ".............................................."
}

1

There are 1 best solutions below

0
zackOverflow On

I was able to resolve this by using a diffrent libeary. I use @arendajaelu/nestjs-passport-apple

$ npm install @arendajaelu/nestjs-passport-apple

My AppleStrategy:

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from '@arendajaelu/nestjs-passport-apple';
import { ConfigService } from '@nestjs/config';
import { readFileSync } from 'fs';

@Injectable()
export class AppleStrategy extends PassportStrategy(Strategy, 'apple') {
  constructor(config: ConfigService) {
    super({
      clientID: config.get<string>('APPLE_CLIENT_ID'),
      teamID: config.get<string>('APPLE_TEAM_ID'),
      keyID: config.get<string>('APPLE_KEY_ID'),
      keyFilePath: readFileSync(
        __dirname + '/../../../apple_secret/apple_secret_key.p8',
      ),
      callbackURL: config.get<string>('APPLE_CALLBACK_URL'),
      passReqToCallback: false,
      scope: ['email', 'name'],
    });
  }
}

Response:

{
"code": "..............................................",
"id_token": "..............................................",
"user": "{"name":{"firstName":"First_Name","lastName":"Last_Name"},"email":"Email"}"
}

NB: The user object is only returned on the first login; the subsiquent login returns code and id_token only.