작성
·
2K
1
안녕하세요 강사님.
OAuth2 인가 프레임워크 관련하여 학습 중 인가서버로부터 받은 access token을 어떻게 저장하고 어떻게 활용할 수 있을지 고민하다가 궁금한 점이 있어 질문드립니다.
[리소스 오너가 소셜 로그인 시 (구글인 경우)]
리소스 오너가 구글 로그인을 한다.
클라이언트 (내가 만든 스프링 서버)는 구글의 인가서버로부터 리소스 오너의 userInfo 엔드포인트 접근 시 사용할 수 있는 access token을 받는다.
access token을 활용해서 userInfo 엔드포인트에 접근하여 리소스 오너의 이메일, 이름 등의 정보를 가져온다. (이 부분은 내가 구현하지 않아도 스프링 시큐리티에서 제공)
소셜 로그인 시 얻은 정보 (oidc 활성화 시 id-token, 리소스 오너가 허용한 userInfo 등)를 클라이언트의 세션에 저장한다.
그리고 로그인 프로세스 완료되어 LoginSuccessHandler에서 이후 로직을 처리할 수 있다.
[이후 로그인 된 상태에서 클라이언트의 API 호출 시]
클라이언트의 API를 호출할 때 SecurityContextHolder에 userInfo를 담아 활용할 수 있다.
access token은 클라이언트에 저장되어 있고, API 호출 시 꺼내어 리소스 서버에 접근할 수 있다.
만약 로그인이 된 상태에서 userInfo 엔드포인트에 접속 시 매번 새로운 access token을 발급 받아서 요청하는 것일까요? (SecurityContextHolder에 access token이 없어서 조금 헷갈리고 있습니다.)
100명의 리소스 오너가 로그인 할 때마다 access token을 발급받으면 총 100개의 access token이 발급되는게 맞을까요?
이러한 경우 클라이언트에 100개의 access token을 저장 후 userInfo 엔드포인트 접근 시 사용하며, 만약 만료되었다면 refresh token으로 access token을 재발급 받아 다시 userInfo 엔드포인트에 접근하는게 맞을까요?
만약 1개의 클라이언트에 100개의 accessToken을 저장 후 만료 전까지 사용하는 것이라면 클라이언트에 부하가 많이 발생하여 scale-out하는 경우에는 보통 어떻게 해결할 수 있을까요?
Google, Naver, Kakao 등의 소셜에서 access token을 발급 받는 것 까지는 스프링 시큐리티가 지원해주지만 이후 다양한 엔드포인트를 호출하거나, access token 만료 시 refresh token으로 재발급 받는 로직 등은 제가 구현해야 하는게 맞을까요?
제가 아직 강의를 절반밖에 듣지 않아서 이후 강의해주시는 부분에 제가 질문드린 내용이 포함되어 있을 수도 있을 것 같습니다. 만약 포함되어 있다면 간략하게나마 어떤 강의 동영상을 참고하면 좋을 지 말씀해주시면 감사하겠습니다.
감사합니다.
답변 1
2
네
전체 질문에 대해 종합적으로 설명하겠습니다.
우리는 소셜로그인을 사용해서 인증을 받는 과정과 인증이후의 과정을 구분해서 이해할 필요가 있습니다.
소셜로그인은 단지 클라이언트에 접속한 사용자로 하여금 최종적으로 인증을 받을 수 있도록 편리한 수단을 제공한다는 점을 먼저 이해해야 합니다.
예를 들어 우리는 오랫동안 전통적인 방식인 폼 로그인을 통해 사용자가 인증을 받는 방식을 많이 취해 왔고 현재도 여전히 존재합니다.
그러나 폼 로그인이 가진 여러가지 단점을 개선할 필요가 생겨나고 좀 더 보안상 안정적이고 편리한 방식으로 인증체계를 갖추어 나갈 수 있는 방법들이 여러 모양으로 생겨났는데 그 중 OAuth2 인증 방식이 가장 널리 사용되는 인가 프레임워크로 발전하게 되고 이를 통해 전통적인 폼 로그인 방식을 대체하는 서비스로까지 성장하게 됩니다.
이 중 소셜로그인 방식은 클라이언트가 직접 운영해야 하는 인가서버를 다른 기관(구글, 네이버, 애플)의 도움을 받아 OAUth2 의 기술적 구현이 가능하도록 한 것이라 볼 수 있습니다.
근데 이것은 곧 전통적인 로그인 방식을 소셜 로그인의 방식으로 대체한 것에 지나지 않습니다.
이 의미는 곧 로그인 이후의 처리방식은 폼 로그인이나 소셜로그인이나 크게 다를 바가 없다는 뜻이기도 합니다.
여기서 중요한 설명을 하나 드리자면 질문하신 내용 중에 SecurityContextHolder 에 access token 이 보이지 않는다고 했는데 그것은 지극히 당연한 결과이고 보일 필요가 없습니다.
SecurityContextHolder 는 인증 이후의 진행을 위해 제공되는 기능이지 인증 과정에 관여하는 객체가 아닙니다. 즉 access_token 는 인증을 위해 제공되는 하나의 수단이지 인증 이후에 필요한 개념이 아니기 때문에 SecurityContextHolder 에서 취급해야 할 요소가 아닙니다.
access_token 은 클라이언트에게 권한을 부여하는 개념에 불과합니다. 어떻게 보면 인증 자체와도 거리가 먼 개념입니다. 단지 인증을 받기 위해 사용자의 정보를 가지고 오기 위한 수단에 가깝습니다.
정확하게 설명하자면 SecurityContextHolder 는 access_token 을 통해 사용자의 정보를 가지고 와서 최종 인증까지 수행한 다음 생성되는 인증 객체가 저장되는 객체이지 access_token 과는 아무런 관련이 없습니다.
제가 위에서 '전통적인 로그인 방식을 소셜 로그인의 방식으로 대체한 것에 지나지 않습니다.' 라고 설명한 것을 잘 생각해 보면 access_token 은 소셜로그인의 방식을 위해 사용되는 수단이며 일단 소셜로그인이 성공하게 되면 그 다음 진행은 세션방식으로 인증을 계속 유지할 것인지, 아니면 세션을 사용하지 않고 JWT 와 같은 토큰 방식으로 인증을 계속 유지할 것인지를 선택하는 결정만 남을 뿐 더 이상 소셜로그인의 과정이 다시 필요하지도 않고 access_token 도 필요 없습니다. 이미 소셜 로그인의 역할은 끝난 것입니다. 사용자가 접속할 때 마다 요청하는 것이 아닙니다.
소셜로그인은 1회적으로 인증을 받으면 되고 그 다음부터는 세션방식의 인증 유지 혹은 토큰 방식의 인증 유지가 필요할 뿐입니다. 만약 세션이 만료되거나 토큰이 만료된다면 다시 소셜로그인을 통해 인증을 받는 식으로 진행하는 것 뿐입니다. 그야 말로 인증이 필요한 상황이 되면 사용하고 인증이 이미 되었으면 그 다음 부터는 인증을 계속 유지하기 위한 절차만 구현 하면 됩니다.
다만 access_token 을 리소스 서버에 접근하기 위한 용도로서 사용해야 한다면 access_token 이 필요할 수는 있으나 여기서 기억해야 할 점은 access_token 은 클라이언트의 리소스 서버가 아닌 access_token 을 제공한 기관들의 리소스 서버로 접근하기 위한 용도여야 합니다. 왜냐하면 access_token 을 제공한 기관들이 access_token 을 검증할 키와 정보들을 가지고 있기 때문입니다.
결론적으로는 SecurityContextHolder 에는 access_token 이 존재하지 않는 것이 맞으며 만약 어떤 이유로 access_token 이 필요하고 이것을 활용할 목적이 있다면 이것을 세션 스토리지 혹은 로컬 스토리지에 저장해서 사용하면 됩니다. 이것은 저의 강의에서 OAuth2AuthorizedClient 를 설명하는 챕터가 있는데 이 강의를 참조하시면 됩니다.
전체적으로 설명드려서 조금 설명이 길었는데 본 강의 전반에 걸쳐 access_token 이 정확하게 무엇인지를 잘 이해하는 것이 더욱 중요하다 할 수 있습니다.
자세하게 답변해주셔서 너무나도 감사합니다.