Back/Node.js

[Node.js] Apple Login Passport 애플 로그인

애플스토어에 앱을 만들어서 제출해야 했다.
회사의 경쟁 업체도 앱을 준비중이라 팀 모두가 속도있게 작업했다.

앱 생태계는 모두 처음이라,
팀원들은 디자인과 마케팅 준비를 하고
나는 법인 DUNS 번호 발급부터 웹뷰 제작과 배포까지 하루정도 공부하고(ㅠ), 다음날 제출했다.

정신없는 일주일이 후루룩 지나갔다.

애플 심사는 하루만에 이뤄졌는데, 리젝을 당했다..ㅎㅎ..

요약
- 카카오, 네이버 소셜로그인은 있는데 왜 애플로그인은 없냐

근데, 이런걸 대비해서 일반로그인까지 만들어서 넣었는데.. 정말..ㅠ
까라면 까야지..

소셜로그인은 라이브러리가 많았는데,
기존 네이버와 카카오 로그인을 만들 때 사용한 passport를 사용하기로 했다. 익숙해서..

 

Apple Developer

Apple 플랫폼에서 개발할 절호의 기회입니다

developer.apple.com

가서 오른쪽 상단 계정(영문)을 클릭해서 계정에 들어간다.


들어가게 되면 애플 로그인 및 권한과 관련된 여러 설정을 할 수 있다.

앱은 이미 있다는 가정 하에, 소셜 로그인만 만들겠다.

등록된 앱이 없다면 Certificates에서 하나 만들면 되겠다.

Identifiers에서 + 버튼을 누르고,

Services IDs를 누르고

그 다음 나오는 Description에는 설명,
Identifier에는 com.뭐시기.service 처럼 작명해준다.

등록을 한 후

Identifiers에서 필터링을 Service IDs로 바꾼다.

누르고,

로그인을 사용할 도메인들을 넣어주고,

Return URLS에는 CallBackURL을 넣어준다.

그 후


Keys에 들어가서

Sign With Apple Login을 설정한 후, 키를 발급받는다.

키는 
AuthKey_2SDL:KSDLKD.P8
이렇게 받는데, 코드에디터로 열어보면 내용을 확인할 수 있다.

코드로 들어간다.


npm install passport-apple

 

passport-apple

Passport strategy for Sign in with Apple

www.npmjs.com


미들웨어 작성

appleStrategy.middleware

require('dotenv').config();
const { mysqlShop, mysqlRead, mysqlWrite } = require('../../model');
const slackErroLogging = require('../../config/slackErrorLoging');
const jwt = require('jsonwebtoken');
const query = require('./query');
const AppleStrategy = require('passport-apple').Strategy;
// req, accessToken, refreshToken, decodedIdToken, profile, cb;
const appleStrategy = new AppleStrategy(
  {
    clientID: process.env.APPLE_CLIENT_ID,
    teamID: process.env.APPLE_TEAM_ID,
    callbackURL: process.env.APPLE_CALL_BACK_URL,
    keyID: process.env.APPLE_KEY_ID,
    privateKeyString: `-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgXITBigCW+l0y3QFZ
Clplfglt8IHVo/UwnkasdasdasdasdasdDsQg5w3ifZt7IsnztEsm1CVW3K
5nGemxkW
-----END PRIVATE KEY-----`,
    passReqToCallback: true,
  },
  async (req, accessToken, refreshToken, decodedIdToken, profile, cb) => {
    process.nextTick(() => cb(null, decodedIdToken));
  },
);

module.exports = appleStrategy;

teamID: Certificates, IDs & Profiles 오른쪽 상단 10자리 문자
clientID
: com.뭐시기.service
keyID: 키에서 생성한 키ID
callbackURL: 아까 등록한 Return URL
privateKeyString: p8파일


카카오, 네이버 패스포트와는 다른게 decodedIdToken은 JWT라이브러리로 해독해서 사용한다.
이런식으로 decodedIdToken을 콜백함수로 넘겨준다.


auth.apple.router

const { Router } = require('express');
const authRouter = Router();
const authController = require('../controller/auth.apple.controller');
const { mysqlShop, mysqlRead, mysqlWrite } = require('../../../model');
const { passport } = require('../../../middlewares');
const { jwtTokenMake } = require('../../../lib');
const query = require('../db/auth.query');
const jwt = require('jsonwebtoken');
require('dotenv').config();

const redirectUrl = process.env.LOGIN_REDIRECT;

authRouter.get('/', passport.authenticate('apple'));
authRouter.post('/oauth', async (req, res, next) => {
  try {
  passport.authenticate('apple', async (err, profile) => {
	const userInfo = jwt.decode(profile);
		-- 코드내용 작성 --
})
  } catch (err) {
    console.log(err);
    return res.status(400).json({ msg: 'fail' });
  } finally {
    shopPool.release();
  }
});

module.exports = authRouter;


profile에 유저 정보가 토큰으로 담겨온다.
담겨온 유저정보를 Jwt라이브러리를 활용해서 해독해준다.

해독하면 객체가 나오는데, 키값 sub가 애플 고유 id이다.
이를 활용하여 로그인 시스템을 만들면 되겠다.