작성자 없음
작성자 정보가 삭제된 글입니다.
해결된 질문
작성
·
1.2K
·
수정됨
1
우선 좋은 강의 감사하다는 말씀드립니다. 올려주신 강의 2편 모두 잘 보고 있고 실무에서 많은 도움을 받고 있습니다.
강사님께 배운 내용을 토대로 인증시스템을 구성해보려던 중 질문 사항이 있어 질문드립니다. 강의에서는 웹애플리케이션 기반 인증에 비중을 두고 설명을 잘 해주셨는데, 모바일 애플리케이션에 대상으로 인증을 구성을 해보려하니 조금 헷갈리는 부분이 있네요.
요구사항은 아래와 같은데요,
추후 내부 리소스를 외부서비스에 제공하기 위한 자체 OAuth2.0인가 서버 구성
모바일 애플리케이션에서 JWT기반 인증을 할 수 있는 인증 및 회원 가입 API
자체 OAuth2 인가서버와 연계하여 구성되는 리소스서버 구성
소셜로그인 기능
인증 시스템을 구성하기 위해 아래와 같은 방법을 생각하고 있습니다.
자체 인증 시스템을 통한 로그인의 경우 자체 모바일앱에 별도의 web view를 생성하고 싶지 않으므로 API로 로그인 정보를 바로 받아서 내부적으로 Resource Owner Password Flow 처리하여 토큰 반환
유저가 모바일앱 UI에 OAuth2 인가서버 계정정보(ID/PASSWORD)를 직접 입력
로그인 버튼 클릭 시, 서버가 계정 정보를 API로 직접 전달받아 내부적으로 Resource Owner Password Flow를 통해 검증하고 토큰 및 인증 필요 정보를 클라이언트에 반환
소셜로그인의 경우, 안전한 인증을 제공하기 위해 모바일 UI에 별도의 webView를 띄우고 Authorization Code Grant방식으로 인증진행
webView를 통해 외부서비스에 대한 Authorization Code Grant 흐름이 진행.
최종적으로 서버가 리다이렉트 주소를 통해 code를 전달받아 소셜 인증이 완료되는 경우(최초 회원인 경우 가입 처리하고), 서버는 자체 리소스서버에서 검증할 수 있는 Access Token을 따로 발급하여 응답하고 이를 모바일앱이 수신하여 인증처리.
질문은 아래와 같습니다.
OAuth2.0 인가서버를 운용하는 경우 자사 모바일 앱의 자체로그인을 Resource Owner Password Flow로 직접 처리하는 것이 일반적인 방법인지? 더 좋은 방법은 없는지?
외부 소셜 로그인의 경우 패스워드 없이 가입처리를 해야하는데 자체인가서버의 회원과 어떻게 일괄적으로 관리가 가능할지?
외부 소셜 로그인의 경우라도 최종 발급되는 토큰은 자체 리소스서버에서 검증가능하도록 자체로그인과 일괄된 방법으로 JWT 발급이 되어야 할 것 같은데, Spring Authorization Server를 통해 효율적으로 구성이 가능할지?
소셜로그인의 경우 서버가 리다이렉트 주소를 통해 code를 받아오더라도 OAuth2AuthorizedClient까지만 확인하고 세션에 인증정보를 저장하고 싶지 않은데 어떻게 효율적으로 custom 가능할지?
oauth2Client API 및 OAuth2AuthorizedClientManager를 통해 토큰을 받아오는 것을 생각하고 있는데 더 합리적인 방법은 없을지?
긴 질문 읽어주셔서 감사합니다. 질문가지수가 많아서 죄송하네요. 답변 주실 수 있는 부분까지만 주셔도 괜찮습니다.혹시 제가 구상하는 방법에서 개선되어야 하는 부분이나 혹시나 제가 잘못 생각하고 있는 부분은 없을 지 이런 부분도 조언해주시면 너무 감사하겠습니다.
답변 1
1
1.OAuth2.0 인가서버를 운용하는 경우 자사 모바일 앱의 자체로그인을 Resource Owner Password Flow로 직접 처리하는 것이 일반적인 방법인지? 더 좋은 방법은 없는지?
자체 인가서버를 운용하고 서비스도 자사에서 운영하는 것이라면 Resource Owner Password Flow 방식으로 인가처리를 하는 것이 무난해 보입니다.
Password 방식의 단점이 인가서버와의 통신 시 사용자의 계정이 네트워크 상에 노출된다는 취약점(물론 ssl 처리는 하겠지만)과 제 3의 서비스(클라이언트)에 제공이 된다는 점 그리고 제 3의 서비스가 인가서버에 가지는 권한이 막강해 진다는 점을 둘 수 있는데
자사 인가서버, 자사 서비스라면 위의 단점이 대부분 없어지므로 크게 문제될 것 같지는 않습니다. 다만 아이디와 패스워드를 사용자로부터 필수적으로 받아야 한다는 점에서 Authoirzation Code 방식에 비해 거쳐야 할 단계가 하나 더 늘어난다는 점 정도입니다.
그리고 현재 Spring Authorization Server 에서는 Resource Owner Password Flow 방식을 아직 지원하지 않고 있습니다. 물론 새롭게 구현해서 추가할 수는 있습니다.
2.외부 소셜 로그인의 경우 패스워드 없이 가입처리를 해야하는데 자체인가서버의 회원과 어떻게 일괄적으로 관리가 가능할지?
소셜 로그인을 통한 회원정보와 자체 인가서버 회원정보 간의 키 역할을 할 수 있는 매개체가 필요합니다.
저의 경험으로는 사용자의 주민번호를 해시한 값으로 사용되는 ci 값을 키로 사용했습니다.
네이버나 카카오는 신청하면 제공하고 있습니다. 애플은 제공하고 있지 않습니다. 그리고 자체 회원같은 경우 최초 회원가입 일 경우 나이스와 같은 기관으로부터 본인인증을 받도록 하면 ci 값을 얻을 수 있습니다.
그렇게 된다면 자체회원정보와 소셜은 ci 를 키로하는 일대다의 관계를 구성할 수 있습니다.
이건 하나의 사례이고 중요한 것은 소셜과 자체 회원 정보간의 키를 어떻게 설계할 것인지 고민해 봐야 합니다.
3.외부 소셜 로그인의 경우라도 최종 발급되는 토큰은 자체 리소스서버에서 검증가능하도록 자체로그인과 일괄된 방법으로 JWT 발급이 되어야 할 것 같은데, Spring Authorization Server를 통해 효율적으로 구성이 가능할지?
음..
토큰을 발급하게 되면 인가서버에서 대칭 혹은 비대칭키로 암호화하고 서명하게 되는데 이 키의 정보는 각 인가서버에서 관리하게 됩니다.
리소스 서버에서 토큰을 검증할 때는 인가서버로부터 jwk(서명시 사용한 키의 정보) 를 가지고 와서 토큰의 유효성을 검증하게 됩니다.
즉 리소스 서버는 소셜로그인에서 발급한 토큰을 검증하기 위한 jwk 가 필요하고 자체인가서버에서 발급한 토큰을 검증하기 위한 jwk 가 필요하게 됩니다.
스프링의 리소스 서버 모듈이 토큰을 검증하는 부분을 기능적으로 제공하고 있지만 소셜과 자체 인가서버의 토큰을 검증하가 위해서는 jwk 설정이 각각 구분되도록 구성해야 합니다.
Spring Authorization Server 가 자체적으로 발급한 토큰과 소셜로그인에서 발급한 JWT 와 통합해서 어떻게 연계가 가능할 지는 여러가지 고민이 되는 부분입니다.
Spring Authorization Server 는 클라이언트에게 토큰을 발급하거나, 취소하거나, 검증하기 위한 용도로서의 역할이고 커스트마이징도 내부적인 API 위주이기 떄문에 외부 기관의 프로세스에 대한 광범위한 커스텀을 제공하고 있지는 않습니다.
리소스 서버가 소셜기관으로 부터 받은 토큰을 가지고 오는 요청과 자체 인가서버에서 발급한 토큰을 가지고 온 요청을 구분해서 받도록 설정을 하고 각 설정에서 소셜인가서버와 자체인가서버로부터 jwk 를 가지고 올 수 있게 구성한다면 서로 다른 기관에서
발급한 토큰이지만 하나의 리소스 서버에서 동시에 검증이 가능하도록 할 수는 있을 것 같습니다. 다만 저도 이부분은 아직 해 보지 않아서 확답까지는 드릴 수 없는 점 양해 부탁드립니다.
4.소셜로그인의 경우 서버가 리다이렉트 주소를 통해 code를 받아오더라도 OAuth2AuthorizedClient까지만 확인하고 세션에 인증정보를 저장하고 싶지 않은데 어떻게 효율적으로 custom 가능할지?
oauth2Client API 및 OAuth2AuthorizedClientManager를 통해 토큰을 받아오는 것을 생각하고 있는데 더 합리적인 방법은 없을지?
일단 세션처리가 되지 않도록 http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 설정을 해야 합니다. 그러면 세션에 인증정보가 저장되지 않습니다.
OAuth2AuthorizedClientManager 는 토큰을 받아오는 것 까지의 역할인데 그렇다면 토큰을 사용해서 사용자의 정보를 가지고 와서 시큐리티가 관리하는 시큐리티 컨텍스트 정보에 저장하는 것 까지의 역할은 누가 할 것인가를 고려해야 합니다.
보통은 시큐리티의 인증 필터에서 모두 처리하지만 OAuth2AuthorizedClientManager 를 필터가 아닌 컨트롤러 단에서 DI 받아 사용한다면 사실 시큐리티 모듈을 벗어나게 됩니다. 그리고 인증처리 역시 컨트롤러 단에서 해야 할 것입니다.
물론 별도의 필터를 만들어서 OAuth2AuthorizedClientManager 를 생성자 등으로 전달해서 필터에서 처리도 가능합니다. 이 내용은 저의 강의에서 소개하고 있으니 참고하시면 됩니다.
또 한가지는 OAuth2LoginAuthenticationFilter 가 소셜기관을 통해 토큰을 발급받고 다시 사용자 엔드포인트로 요청해서 정보를 가지고 온 다음 인증처리까지 완료하는 필터인데 인증에 성공한다면 successfulAuthentication() 에서 인증후속 처리를 하게 됩니다.
가장 핵심적인 처리인 securityContext 에 인증객체(Authentication) 를 저장하고 있습니다.
필요하다면 OAuth2LoginAuthenticationFilter 를 상속받든지 아니면 OAuth2LoginAuthenticationFilter 의 부모격인 AbstractAuthenticationProcessingFilter 를 상속받고 내부 소스를 최대한 활용하고 successfulAuthentication() 메소드를 오버라이드 해서 원하시는 후속처리를 할 수도 있습니다. 우선적으로 세션은 사용할 수 없도록 설정해 놓았기 때문에 여기서 어떤 방식으로 사용자의 인증처리를 구현하든지 세션과는 상관없습니다.
한가지 궁금한 것은 oauth2Client API 및 OAuth2AuthorizedClientManager를 통해 토큰을 받아오는 것이라고 했는데 이것을 통해 최종 구현하려고 하는 것이 무엇인가요?
일단 두서 없이 답변을 드렸는데 좋은 답변이 되었는지 잘 모르겠습니다.
p.s.
아 ! 처음 질의했을 때 개발자라면 다 아는 분과 동일한 이름이라 조금 놀랬습니다.^^
한가지 궁금한 것은 oauth2Client API 및 OAuth2AuthorizedClientManager를 통해 토큰을 받아오는 것이라고 했는데 이것을 통해 최종 구현하려고 하는 것이 무엇인가요?
소셜로그인 성공 이후 OAuth2AuthorizedClient 정보를 토대로 컨트롤러단에서 자체 인가시스템의 JWT를 발급하여 반환하는 후속 처리를 구현하려고 하였는데요. 조언해주신대로 세션 설정을 끄고 시큐리티모델을 최대한 활용하여 SecurityContext 정보를 활용하는 방향이 합리적일 것 같습니다. 제가 생각이 조금 짧았던거 같네요.
짧지 않은 질문이었는데, 너무나도 정성스런 답변 정말 감사합니다. 답변주신 내용이 큰 도움이 될 것 같습니다.
좋은 퀄리티 강의 제공해주셔서 감사하고, 앞으로도 좋은 지식공유 활동 이어나가시길 응원하겠습니다.
(제가 유명하신 분과 동명이인이라 안그래도 오해하실까 일부러 닉네임 변경했는데 그 사이 캐치를 하셨군요ㅎㅎ)