팀 프로젝트를 진행하며 다음과 같은 요구사항이 발생했습니다.
1. 특정 워크스페이스 구성원인지 식별할 수 있어야 한다
2. 내부 구성원이라면 해당 사용자를 식별할 수 있는 정보를 확보해야 한다
이를 구현할 방법에 대해 탐색한 결과를 간단히 기록해봅니다
OAuth Flow
OAuth Flow 를 이해하는 데에 시간이 많이 필요했습니다.
레벨2에서 인증, 인가를 학습하며 RFC 문서를 통해 인증 서버와 자원 서버를
구분하여 사용한다는 개념은 미리 습득해두었지만,
이를 하나의 사용자 관점에서만 접근했었기 때문에 미싱 링크가 존재했습니다.
사용자와 두 개의 서비스가 존재할 때,
서비스 A는 사용자에 대한 인증을 서비스 B에 의존하는 상황이라면
상호작용하는 대상이 셋이 되고, 이 경우에 대한 이해가 추가적으로 필요했습니다.
결과적으로 제가 현재 이해한 흐름은 다음과 같습니다.
1. 리차드는 줍줍 서비스 중 인증이 필요한 페이지에 접속 시도합니다.
2. 줍줍 서비스는 사용자를 Slack 로그인 페이지로 Redirect합니다.
3. 리차드는 Slack 로그인을 수행합니다. 그리고 다시 줍줍 서비스로 Redirect 됩니다.
4. 로그인 결과에는 Slack 인증 서버가 발급한 인증 코드가 포함됩니다. 이를 줍줍 서비스가 확인합니다.
5. 줍줍은 인증 코드를 Slack 인증 서버에 전달하여 리차드 전용 access_token을 받습니다.
6. 줍줍은 리차드 전용 access_token을 Slack 자원 서버에 전달하여 리차드 프로필 정보를 받습니다.
7. 리차드를 식별한 결과를 이용해 줍줍 서비스 전용 access_token을 리차드에게 반환하며 로그인 처리합니다.
특정 워크스페이스 구성원인지 식별하기
이 요구사항은 워크스페이스 내부인에게만 공개되어야할 정보를
외부에 노출시키지 않기 위해 존재합니다.
따라서 굉장히 중요한 요구사항인데요,
이를 구현할 방법으로 가장 먼저 떠올린 방법은 다음과 같습니다.
워크스페이스 내 전체 유저 정보를 저장해두고, 로그인 시점에 식별하기
1. Slack App을 생성하고, 워크스페이스 내 유저 정보를 확인할 수 있는 권한을 부여한다.
2. Slack App을 워크스페이스에 설치한다.
3. 설치된 Slack App의 토큰을 이용해 Slack API를 호출하여 워크스페이스 내 모든 유저 정보를 가져온다.
4. 유저 정보를 데이터베이스에 저장한다.
5. 추후 유저가 탈퇴하거나 새로 진입하는 경우, 이를 이벤트로 받아서 건마다 처리한다. (이벤트 권한 추가 필요)
그러나 위 방법의 경우 개인정보 관련 이슈가 있었습니다.
영문과 숫자의 조합으로 이루어진 사용자 ID라고 하더라도
동의되지 않은 개인의 식별값을 데이터베이스에 저장하는 것은 민감할 수밖에 없었습니다.
그로인해 개개인에게 동의를 구하거나,
서비스 사용 신청 구글폼을 받는 등의 접근성이 비교적 떨어지는 대안들을 생각했었는데요,
다행히도 이 작업을 Slack에게 위임할 수 있었습니다.
Slack OAuth 시점에 워크스페이스 ID를 전달해 구성원만 통과시키라고 위임하기
When a valid team ID is passed to team and
the authenticating user is already signed in to that workspace,
passing this parameter ensures the user will auth against that workspace.
https://api.slack.com/authentication/oauth-v2#asking__how-the-team-parameter-behaves
Slack 인증서버로 사용자를 Redirect 하는 시점에 Query Parameter로 team을 전달할 수 있습니다.
이 team 파라미터에 워크스페이스 아이디를 전달하면,
해당 워크스페이스의 구성원인 경우에만 Slack 인증서버가 인증 코드를 발급해줍니다.
워크스페이스의 team 아이디는 stackoverflow를 참고하여 얻었습니다.
크롬에서 워크스페이스에 로그인 한 뒤, 개발자도구를 열고 team 으로 검색해서 얻을 수 있었습니다.
다른 우아한 방법이 있을 것 같은데 빨리 찾은 방법으로 일단 해결했습니다.
구성원이 아니면 정말 처리가 안되나? 어떻게 되나? 테스트해봤습니다.
사용자가 줍줍 서비스로 돌아가려면 뒤로가기를 눌러야 하는 불편함 까지는 처리하기 어려운 것 같습니다만
특정 워크스페이스 내부 구성원인지 식별하기 요구사항은
다행히도 Slack의 지원으로 간단히 해결되었습니다.
로그인 사용자의 정보 얻기
특정 워크스페이스 구성원인 경우에만 인증 코드가 발급되도록
Slack 인증 서버로 Redirect 시 team 이라는 Query Parameter를 전달하는 것까지 알아봤습니다.
Slack에 존재하는 사용자이긴 하지만, 해당 워크스페이스 구성원이 아닌 경우
인증 코드 발급이 진행되지 않는 것을 살펴봤으니 이제 성공 케이스 Flow를 계속 따라가보겠습니다.
줍줍이 Slack 인증 서버로 리차드를 Redirect 시킬 때,
team 말고 추가로 보내는 Query Parameter가 있습니다.
바로 redirect_url 인데요, 이 값은 로그인 프로세스 이후에
Slack 인증 서버가 리차드를 어디로 Redirect 시킬지 식별하는데에 사용됩니다.
리차드 Slack 로그인 시켜서 인증 코드 받기
예를 들자면 아래와 같은 형식으로 줍줍에서 사용자를 Redirect 하고요,
https://Slack인증서버?team=특정워크스페이스&redirect_url=https://줍줍서버
로그인 처리 이후 redirect_url 로 사용자가 Redirect될 땐 다음과 같이 옵니다.
https://줍줍서버?code=리차드용 인증코드
리차드용 인증 코드를 리차드용 access_token으로 교환하기
줍줍 서비스에서는 인증 코드값을 받아야 합니다.
그리고 이를 다시 Slack으로 보내서 리차드 전용 access_token을 받아야 합니다.
아래와 같이 Slack 인증 서버에 요청을 보냅니다.
https://Slack인증서버?client_id={Slack App id}&client_secret={Slack App secret}&code={리차드용 인증코드}
client_id와 client_secret은 Slack 인증 서버에서 줍줍 서비스를 식별하는 값이라고 생각하시면 될 것 같습니다.
(정확히는 Slack App의 id와 인증값이지만 OAuth로 추상화해서 이야기하는 게 더 나을 것 같아서요~)
Slack 정책상 발급됐던 리차드용 인증코드는 10분간 유효합니다.
10분 내에 위 요청을 보내서 인증코드와 access_token을 교환해야 합니다.
응답은 아래와 같이 옵니다.
{
"authed_user": {
"id": "team으로 전달됐던 워크스페이스 내 리차드 Slack 계정 식별자",
"scope": "요청할 수 있는 자원 범위",
"access_token": "리차드용 엑세스 토큰",
},
"team": {
"id": "team으로 전달됐던 워크스페이스 식별자"
},
}
일부 불필요한 내용은 제거했습니다.
현재 저희 서비스의 요구사항을 충족하기 위해 여기에서 필요한 것은 id와 access_token입니다.
개인을 식별할 수 있는 식별값은 얻었지만, 추가적인 정보를 조금만 더 가져와봅시다.
리차드용 accesss_token으로 리차드 정보 가져오기
GET https://슬랙 자원서버/사용자정보
Authorization: Bearer {리차드 엑세스 토큰}
Slack 인증서버에게 리차드 인증 코드를 보내고 받은 리차드용 엑세스 토큰을
Bearer 인증 방식으로 전달하면 정보를 가져올 수 있습니다.
그 중 일부만 보자면 다음과 같습니다.
{
"https://slack.com/user_id": "해당 워크스페이스 내 Slack 계정 식별자",
"https://slack.com/team_id": "Slack 워크스페이스 식별자",
"name": "이름",
"picture": "프로필 이미지 주소",
}
식별자, 이름, 프로필 이미지 주소 정도만 데이터베이스에 저장해도
요구사항은 충분히 달성될 것 같습니다.
기타
Slack App 에 Redirect_URL을 미리 세팅해두고,
Query Parameter 가 등록된 Redirect_URL과 일치하는지 확인하는 과정도 있습니다.
https 만 허용되는데요, 배포하지 않더라도 일단 없는 https로 세팅해두고
Redirect 시 Query Parameter로 인증 코드가 어떻게 전달되는지 확인할 수 있습니다.
그 다음에는 Postman 등을 이용해서 인증 코드를 엑세스 토큰으로 바꾸고
이를 이용해 사용자 정보를 요청할 수 있습니다.
이하는 관련 링크들입니다.
https://api.slack.com/authentication/oauth-v2
https://api.slack.com/authentication/sign-in-with-slack#implementation
'우아한테크코스 4기' 카테고리의 다른 글
@Transactional 테코톡 완료! (4) | 2022.07.22 |
---|---|
IntelliJ 플러그인으로 Co-authored-by 설정하기 (0) | 2022.07.19 |
Git Flow 가 CI/CD 와 어울리지 않는 이유 by David Farley (0) | 2022.07.14 |
🥄 Git Flow 한 스푼 (0) | 2022.07.14 |
아이디어 매몰 주의 - (인지적 구두쇠, 기억 편집) (0) | 2022.07.09 |