Google OAuth2 인증 방식 이해하기

목차

Google Oauth2 인증 시나리오 살펴보기

  1. Web Server가 Google에 Access Token 을 요청한다.
  2. 사용자가 구글 ID와 Password를 이용해 로그인을 한다.
  3. Web Server쪽으로 Authorization code 가 반환된다.
  4. Authorization code를 이용해 Access Token을 요청
  5. 구글에서 Access Token값을 반환한다.
  6. Access Token을 이용해 사용자의 profile과 같은 정보들을 가져온다.

스프링에서 기본적으로 제공하는 OAuth2Provider

Google, Facebook, Github 등을 통해 OAuth2인증하기 위한 기본적인 설정값들이 들어가 있다.

  • authorizationUri
    • 인증을 진행하기 위해 사용하는 URI
  • tokenUri
    • Resource server 로부터 Access token 을 받기 위해 사용하는 URI
  • jwkSetUri
    • Google로 부터 받은 JWT(JSON Web Token) 의 유효성을 확인할 수 있는 Public key(JSON Web Key) 를 받을 수 있는 URI
  • userInfoUri
    • Resource Server (ex. Google) 로부터 사용자 정보를 가져오기 위한 URI
  • userNameAttributeName
    • Resource server 가 제공하는 id값
  • clientName
    • Resource Server 이름 (client Name을 사용할 때도 있다.)
public enum CommonOAuth2Provider {
GOOGLE {
@Override
public Builder getBuilder(String registrationId) {
ClientRegistration.Builder builder = getBuilder(registrationId, ClientAuthenticationMethod.BASIC,
DEFAULT_REDIRECT_URL);
builder.scope("openid", "profile", "email");
builder.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth");
builder.tokenUri("https://www.googleapis.com/oauth2/v4/token");
builder.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs");
builder.issuerUri("https://accounts.google.com");
builder.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo");
builder.userNameAttributeName(IdTokenClaimNames.SUB);
builder.clientName("Google");
return builder;
}
},
...

private static final String DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}";

protected final ClientRegistration.Builder getBuilder(String registrationId, ClientAuthenticationMethod method,
String redirectUri) {
ClientRegistration.Builder builder = ClientRegistration.withRegistrationId(registrationId);
builder.clientAuthenticationMethod(method);
builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE);
builder.redirectUri(redirectUri);
return builder;
}
}

jwkSetUri의 URI로 접속

https://www.googleapis.com/oauth2/v3/certs

// 20210131104458
// https://www.googleapis.com/oauth2/v3/certs

{
"keys": [
{
"use": "sig",
"kid": "eea1b1f42807a8cc136a03a3c16d29db8296daf0",
"n": "0zNdxOgV5VIpoeAfj8TMEGRBFg-gaZWz94ePR1yxTKzScHakH4F4wcMEyL0vNE-yW_u4pOl9E-hAalPa2tFv4fCVNMMkmKwcf0gm9wNFWXGakVQ8wER4iUg33MyUGOWj2RGX1zlZxCdFoZRtshLx8xcpL3F5Hlh6m8MqIAowWtusTf5TtYMXFlPaWLQgRXvoOlLZ-muzEuutsZRu-agdOptnUiAZ74e8BgaKN8KNEZ2SqP6vE4w16mgGHQjEPUKz9exxcsnbLru6hZdTDvXbX9IduabyvHy8vQRZsqlE9lTiOOOC9jwh27TXsD05HAXmNYiR6voekzEvfS88vnot2Q",
"e": "AQAB",
"kty": "RSA",
"alg": "RS256"
},
{
"n": "rKZ-1zdz_CoLekSynOtyWv6cPSSkV28Kb9kZZHyYL-yhkKnH_bHl8OpWiGxQiKP0ulLRIaq1IhSMetkZ8FfXH-iptIDu4lPb8gt0HQYkjcy3HoaKRXBw2F8fJQO4jQ-ufR4l-E0HRqwLywzdtAImNWmju3A4kx8s0iSGHGSHyE4EUdh5WKt-NMtfUPfB5v9_2bC-w6wH7zAEsI5nscMXnvz1u8w7g2_agyhKSK0D9OkJ02w3I4xLMlrtKEv2naoBGerWckKcQ1kBYUh6WASPdvTqX4pcAJi7Tg6jwQXIP1aEq0JU8C0zE3d33kaMoCN3SenIxpRczRzUHpbZ-gk5PQ",
"e": "AQAB",
"use": "sig",
"kid": "03b2d22c2fecf873ed19e5b8cf704afb7e2ed4be",
"kty": "RSA",
"alg": "RS256"
}
]
}

userInfoUri EndPoint에 접속

token_uri로부터 받은 access token을 사용하여 https://www.googleapis.com/oauth2/v3/userinfo?access_token={Google로부터 받은 Access Token} 해당 형식으로 URI에 접속하게 되면 User와 관련된 JSON값을 받을 수 있다.

{
"sub": "",
"name": "사용자 성+이름",
"given_name": "사용자 이름",
"family_name": "사용자 성",
"picture": "구글에서 사용하는 내 사진",
"email": "구글 email",
"email_verified": true,
"locale": "ko"
}

sub 필드는 Google서비스에서 계정마다 부여하는 id 값이다.

Share