1. 인증
- 인증은 크고 복잡한 주제이다.
- 웹앱에서 빼놓을 수 없는 중요한 주제이고, 제발 직접 만들려고 하지 말자.
- 앱의 보안시스템을 이해하는 것은 중요하지만, 직접 구현하는 시도는 '보안 전문가' 가 아니라면 접어두는 것이 좋다.
2. 인증과 권한 부여
- 인증은 사용자를 확인하는 작업이다. (Authentication)
- 권한부여는 사용자에게 접근/수정/볼 권한을 주는 것이다.(Authorization)
- 인증은 AuthN, 권한부여는 AuthZ라고 짧게 표기하는 사례가 많다.
3. 비밀번호 문제
- 비밀번호에서 문제는 사람이다. 사람이 만들기 때문에 가장 약한 고리이다.
- 2018년 보안 분석 결과 대부분의 비밀번호가 '123456' 이었고, 'password'가 두 번째로 많았다고 한다.
- 특수문자가 포함된다고 난리를 쳐도 'password1!' 같은걸 사용한다.
- 웹개발자가 할 수 있는 일은 별로 없다. 그나마 서드파티에 인증 위임하는 것 혹은 비밀번호 관리서비스와 연동하도록 하는 것이다.
4. 서드파티 인증(OAuth)
- 세가지 주요 장점이 있다.
- 인증 부담이 줄어들고, 서트파티와 협력하기만 하면 된다.
- 다양한 계정을 사용하면서 생기는 비밀번호 고갈을 피할 수 있다.
- 이미 가지고 있는 자격 증명으로 사이트를 빠르게 이용할 수 있다.
- 단점도 있다.
- 단점은 구글/페이스북/트위터/링크드인 등에 계정이 아예 없는 사람들이 있다. 이정도면 그냥 웹서비스를 이용하지 않는건지 뭔사람이야 도대체? 고연령층은 이해한다만, 어쨌든 그런 사람들은 못쓴다.
5. DB에 사용자 저장
- 서드파티 인증과 관계 없이 DB에 사용자 정보를 저장하는 것이 좋다.
실제로 사용하고 있는 사이드프로젝트의 User Schema 예제
- 서드파티에서 사용할 필드를 추가해서 사용해야 한다. 다중 인증을 사용한다면, 충돌방지를 위해 인증타입과 서드파티 ID의 조합으로 만든다. 예를들면 authId 는 facebook:525759301 뭐 이런식이다.
6. 인증과 등록, UX
- 인증은 신뢰할 수 있는 서드파티, 또는 사용자에게 지급한 사용자 이름과 비밀번호 같은 자격 증명을 통해 사용자를 확인하는 것이다.
- 사용자가 처음 방문했을 때, 혹은 어떠한 서비스를 사용하고자 할 때 등록해야 한다는 것이 명확히 드러나야 한다.
- 사용자 자신이 사이트에 등록하고 있다는 것을 명확히 인지해야 하며, 탈퇴고 쉽게 가능해야 한다.
- 사용자의 이메일 주소를 저장해뒀다면, 이메일로 어떤 서비스를 통해 인증해썼는지 알리는 방법을 사용하면 좋다.
7. 패스포트
- 패스포트는 노드/익스프레스에서 널리 쓰이는 강력한 인증모듈이다.
- 패스포트는 전략패턴을 통해 한 가지 인증 메커니즘이 아니라 여러가지 다양한 인증 방법을 플러그인처럼 사용한다.
- 서드파티가 비밀번호를 처리하고, 이후 과정은 리디렉트에 의존한다.
- 페이지 -> 302/307 -> 서드파티 로그인 팝업 혹은 페이지 -> 302/307 -> 인증됨페이지
- 브라우저는 HTTP 요청을 만들고, 응답을 표시하고, 리디렉트를 수행하는 세 가지 역할을 한다.
1) 로그인페이지 :
- 로그인 방법을 정하는 곳
- 인증이 필요한 페이지/서비스에 접속하고자 한다면 이 페이지로 리디렉트해야한다.,
2) 인증 요청 생성 :
- 리디렉트를 통해 서드파티에 전송될 요청을 만든다.
- 패스포트와 플러그인이 이 단계의 세부사항을 처리한다.
- 인증요청에는 중간자 공격(MITM)을 포함해 공격 수단으로부터 보호한다.
- 서드파티 인증 메커니즘에 대한 추가 정보를 요청한다.
3) 인증 응답 확인 :
- 서드파티에서 인증이 완료되면 유효한 인증 응답을 봬며, 이를 통해 사용자를 확인한다.
- 인증 응답에는 해당 서드파티에서 고유한 ID가 포함되며, 2단계에서 요청한 추가 정보도 포함된다.
- 4단계로 이동하기 위해서는 사용자가 인증되었음을 반드시 기억해야 한다. 쿠키나 세션을 사용하지만, 세션을 보통 권한다.
4) 인증 확인
- 사용자 ID가 있으면 DB에서 사용자가 어떠한 권한을 가졌는지에 관한 정보가 담긴 사용자 객체를 가져올 수 있다.
- 이런 방식을 사용하면 모든 요청마다 서드파티 인증을 통할 필요가 없다.
- 인증을 위해 패스포트를 사용하는 것도 작업량이 만만치는 않다.
- 인증솔루션을 개인화하고자 한다면 패스포트가 좋은 출발점이 된다.
8. 패스포트 설정
- 페이스북을 예시로 한다.
- 페이스북 인증을 위해서는 페이스북 앱이 필요하다.
- 적당한 페이스북 앱이 있다면 그걸 쓰면 되고, 없다면 인증 전용으로 하나 만들어도 된다.
- 기관의 공식 페이스북 계정으로 앱을 만든다.
- 개인 페이스북 계정을 해당 앱의 관리자로 추가할 수도 있다.
- 개발/테스트 목적에 사용하려면 개발/테스트용 도메인 이름을 앱과 연결해야 한다.
- 페이스북에서는 localhost와 포트 번호를 허용하므로 테스트 목적으로 알맞다.
- 앱을 테스트하기 위해 브라우저에 입력하는 URL이 페이스북 앱과 연결된다.
- 페이스북 개발자 문서를 확인하여 앱 설정을 한다.
- 이후에는 앱ID와 앱 시크릿이 필요하다. 페이스북 앱 관리 페이지에서 찾을 수 있다.
- 콜백 URL의 호스트 이름과 포트가 앱에서 설정한 것과 일치하는지 확인하려면 브라우저의 URL에서 인코드된 URL의 쿼리스트링에서 단서를 찾을 수 있다.
- 이제 페이스북 인증 플러그인을 설치한다.
npm i passport passport-facebook
- lib/auth.js 모듈같이 파일을 만들어 조각조각내어 나눈다.
- 패스포트에 필요한 serializeUser와 deserializeUser 메서드를 먼저 만든다.
- 패스포트는 serializeUser와 deserializeUser를 사용해 요청을 인증된 사용제에 연결하므로 어떤 스토리지든 호환된다.
- 우리는 DB ID(_id)를 세션에 저장하기만 한다.
- 이 작업이 끝나면 필요할 때 이 ID를 DB에서 찾아 사용자 객체를 가져온다.
- 이 메서드를 만들면, 활성화된 세션이 있고 인증이 잘 되었다면 req.session.passport.user는 db에서 가져온 사용자객체가 된다.
- 다음은 내보낼 것을 선택할 차례이다.
- 우선 패스포트를 초기화해야하고, 인증과 함께 서드파티 인증 서비스에서 리디렉트한 콜백을 처리할 라우트를 등록해야 한다.
- 이 모듈에서 이 작업을 하는 함수를 내보내기보다 필요한 메서드를 가진 객체를 반환하는 함수를 내보낸다.
- 설정값을 넣어줘야 하기 때문이다.
- 객체를 반환하는 함수를 반환하는 이유는 아래와 같다
- 그리고나서 credentials.development.json 에 authProviders 프로퍼티를 추가해야 한다.
"authProviders":{
"facebook":{
"appId":"your_app_id",
"appSecret":"your_app_secret"
}
}
- 이제 TODO 영역에 패스포트 템플릿을 통해 인증되고 난 후 FacebookStrategy 함수를 호출하면 된다.
- 그려면 profile 매개변수에 페이스북 사용자에 대한 정보가 담긴다. 여기 페이스북 ID가 들어가게 되고, 이 ID로 계정을 우리의 사용자 객체에 연결하면 된다.
- TODO의 registerRoutes 메서드도 만들어준다.
- 이제 /auth/facebook 에 방문하면 자동으로 페이스북 인증화면으로 리디렉트한다.
- 쿼리스트링 매개변수 redirect가 있는지 확인하고, 있다면 세션에 저장한다.
- 인증하면 /auth/facebook/callback 경로로 리디렉트한다.
- passport.use() 추가를 통해 다양한 인증 제공자를 추가할 수 있다.
어유 복잡해.
'더이상 하지 않는 Backend - NodeJS > Node-Express 개론(완)' 카테고리의 다른 글
[O'REILLY] Node & Express - 20장 : 디버깅 (0) | 2023.04.21 |
---|---|
[O'REILLY] Node & Express - 19장 : 서드파티 API (0) | 2023.04.21 |
[O'REILLY] Node & Express - 18장 : 보안 처리 (0) | 2023.04.17 |
[O'REILLY] Node & Express - 17장 : 정적 콘텐츠 (0) | 2023.04.13 |
[O'REILLY] Node & Express - 15장 : REST API와 JSON (0) | 2023.04.11 |
댓글