OpenID Connect

Google의 OAuth 2.0 API는 인증과 승인 모두에 사용할 수 있습니다. 이 문서에서는 OpenID Connect 사양을 준수하고 OpenID 인증을 획득한 인증용 OAuth 2.0 구현을 설명합니다. OAuth 2.0을 사용하여 Google API에 액세스하기에 있는 문서도 이 서비스에 적용됩니다. 이 프로토콜을 대화형으로 살펴보려면 Google OAuth 2.0 플레이그라운드를 사용하는 것이 좋습니다. Stack Overflow에서 도움을 받으려면 질문에 'google-oauth' 태그를 지정하세요.

OAuth 2.0 설정

애플리케이션에서 사용자 로그인에 Google의 OAuth 2.0 인증 시스템을 사용하려면 먼저 Google API Console 에서 프로젝트를 설정하여 OAuth 2.0 사용자 인증 정보를 가져오고 리디렉션 URI를 설정하고 (선택사항) 사용자가 사용자 동의 화면에 보는 브랜딩 정보를 맞춤설정해야 합니다. API Console 를 사용하여 서비스 계정을 만들고, 결제를 사용 설정하고, 필터링을 설정하고, 기타 작업을 할 수도 있습니다. 자세한 내용은 Google API Console도움말을 참고하세요.

OAuth 2.0 사용자 인증 정보 가져오기

사용자를 인증하고 Google API에 액세스하려면 클라이언트 ID 및 클라이언트 비밀번호를 비롯한 OAuth 2.0 사용자 인증 정보가 필요합니다.

要查看给定OAuth 2.0凭据的客户端ID和客户端密钥,请单击以下文本: 选择凭据 。在打开的窗口中,选择您的项目和所需的凭证,然后单击“ 查看”

或者,从API Console的“ 凭据”页面中查看您的客户端ID和客户端密钥:

  1. Go to the Credentials page.
  2. 单击您的凭证名称或铅笔( )图标。您的客户ID和密码位于页面顶部。

리디렉션 URI 설정

API Console 에서 설정하는 리디렉션 URI는 Google에서 인증 요청에 대한 응답을 전송하는 위치를 결정합니다.

要创建,查看或编辑给定OAuth 2.0凭据的重定向URI,请执行以下操作:

  1. Go to the Credentials page.
  2. 在页面的OAuth 2.0客户端ID部分中,点击一个凭据。
  3. 查看或编辑重定向URI。

如果“凭据”页面上没有OAuth 2.0客户端ID部分,则您的项目没有OAuth凭据。要创建一个,点击创建凭证

사용자 동의 화면 맞춤설정

사용자의 경우 OAuth 2.0 인증 환경에는 사용자가 공개하는 정보와 적용되는 약관을 설명하는 동의 화면이 포함됩니다. 예를 들어 사용자가 로그인할 때 앱에 이메일 주소와 기본 계정 정보에 대한 액세스 권한을 부여하라는 메시지가 표시될 수 있습니다. 앱이 인증 요청에 포함하는 scope 매개변수를 사용하여 이 정보에 대한 액세스를 요청합니다. 범위를 사용하여 다른 Google API에 대한 액세스 권한을 요청할 수도 있습니다.

사용자 동의 화면에는 제품 이름, 로고, 홈페이지 URL과 같은 브랜딩 정보도 표시됩니다. API Console에서 브랜드 정보를 관리합니다.

프로젝트의 동의 화면을 활성화하려면 :

  1. 열기 Consent Screen page 에서 Google API Console .
  2. If prompted, select a project, or create a new one.
  3. 양식을 작성하고 저장을 클릭 하십시오 .

다음 동의 대화상자는 요청에 OAuth 2.0 및 Google Drive 범위 조합이 포함된 경우 사용자에게 표시되는 내용을 보여줍니다. 이 일반 대화상자는 Google OAuth 2.0 플레이그라운드를 사용하여 생성되었으므로 API Console에 설정되는 브랜딩 정보는 포함되지 않습니다.

동의 페이지 스크린샷

서비스 액세스

Google 및 서드 파티는 사용자 인증 및 Google API 액세스 권한 획득의 많은 구현 세부정보를 처리하는 데 사용할 수 있는 라이브러리를 제공합니다. 예를 들어 다양한 플랫폼에서 사용할 수 있는 Google ID 서비스Google 클라이언트 라이브러리가 있습니다.

라이브러리를 사용하지 않으려면 사용 가능한 라이브러리의 기반이 되는 HTTP 요청 흐름을 설명하는 이 문서의 나머지 부분에 있는 안내를 따르세요.

사용자 인증

사용자를 인증하려면 ID 토큰을 가져와서 유효성을 검사해야 합니다. ID 토큰은 인터넷에서 ID 어설션을 공유하는 데 사용하도록 설계된 OpenID Connect의 표준화된 기능입니다.

사용자를 인증하고 ID 토큰을 얻는 데 가장 일반적으로 사용되는 접근 방식을 '서버' 흐름과 '암시적' 흐름이라고 합니다. 서버 흐름을 사용하면 애플리케이션의 백엔드 서버가 브라우저 또는 휴대기기를 사용하는 사용자의 ID를 확인할 수 있습니다. 암시적 흐름은 클라이언트 측 애플리케이션 (일반적으로 브라우저에서 실행되는 JavaScript 앱)이 백엔드 서버를 통해서가 아니라 API에 직접 액세스해야 하는 경우에 사용됩니다.

이 문서에서는 사용자 인증을 위한 서버 흐름을 실행하는 방법을 설명합니다. 암시적 흐름은 클라이언트 측에서 토큰을 처리하고 사용하는 데 보안 위험이 있으므로 훨씬 더 복잡합니다. 암시적 흐름을 구현해야 하는 경우 Google ID 서비스를 사용하는 것이 좋습니다.

서버 흐름

앱이 이러한 프로토콜을 사용하고 사용자를 인증할 수 있도록 API Console에서 앱을 설정해야 합니다. 사용자가 Google 계정으로 로그인하려고 하면 다음을 실행해야 합니다.

  1. 위조 방지 상태 토큰 만들기
  2. Google에 인증 요청 보내기
  3. 위조 방지 상태 토큰 확인
  4. code를 액세스 토큰 및 ID 토큰으로 교환
  5. ID 토큰에서 사용자 정보 가져오기
  6. 사용자 인증

1. 위조 방지 상태 토큰 만들기

요청 위조 공격을 방지하여 사용자의 보안을 보호해야 합니다. 첫 번째 단계는 앱과 사용자의 클라이언트 간에 상태를 유지하는 고유한 세션 토큰을 만드는 것입니다. 나중에 이 고유한 세션 토큰을 Google OAuth 로그인 서비스에서 반환한 인증 응답과 일치시켜 사용자가 요청한 것인지 아니면 악의적인 공격자가 요청한 것인지 확인합니다. 이러한 토큰을 크로스 사이트 요청 위조(CSRF) 토큰이라고도 합니다.

상태 토큰으로 적합한 선택은 고품질 난수 생성기를 사용하여 구성된 30자 정도의 문자열입니다. 또 다른 하나는 백엔드에서 비밀로 유지되는 키로 일부 세션 상태 변수를 서명하여 생성된 해시입니다.

다음 코드는 고유한 세션 토큰을 생성하는 방법을 보여줍니다.

PHP

이 샘플을 사용하려면 PHP용 Google API 클라이언트 라이브러리를 다운로드해야 합니다.

// Create a state token to prevent request forgery.
// Store it in the session for later validation.
$state = bin2hex(random_bytes(128/8));
$app['session']->set('state', $state);
// Set the client ID, token state, and application name in the HTML while
// serving it.
return $app['twig']->render('index.html', array(
    'CLIENT_ID' => CLIENT_ID,
    'STATE' => $state,
    'APPLICATION_NAME' => APPLICATION_NAME
));

자바

이 샘플을 사용하려면 Java용 Google API 클라이언트 라이브러리를 다운로드해야 합니다.

// Create a state token to prevent request forgery.
// Store it in the session for later validation.
String state = new BigInteger(130, new SecureRandom()).toString(32);
request.session().attribute("state", state);
// Read index.html into memory, and set the client ID,
// token state, and application name in the HTML before serving it.
return new Scanner(new File("index.html"), "UTF-8")
    .useDelimiter("\\A").next()
    .replaceAll("[{]{2}\\s*CLIENT_ID\\s*[}]{2}", CLIENT_ID)
    .replaceAll("[{]{2}\\s*STATE\\s*[}]{2}", state)
    .replaceAll("[{]{2}\\s*APPLICATION_NAME\\s*[}]{2}",
    APPLICATION_NAME);

Python

이 샘플을 사용하려면 Python용 Google API 클라이언트 라이브러리를 다운로드해야 합니다.

# Create a state token to prevent request forgery.
# Store it in the session for later validation.
state = hashlib.sha256(os.urandom(1024)).hexdigest()
session['state'] = state
# Set the client ID, token state, and application name in the HTML while
# serving it.
response = make_response(
    render_template('index.html',
                    CLIENT_ID=CLIENT_ID,
                    STATE=state,
                    APPLICATION_NAME=APPLICATION_NAME))

2. Google에 인증 요청 전송

다음 단계는 적절한 URI 매개변수를 사용하여 HTTPS GET 요청을 만드는 것입니다. 이 프로세스의 모든 단계에서 HTTP 대신 HTTPS를 사용합니다. HTTP 연결은 거부됩니다. authorization_endpoint 메타데이터 값을 사용하여 탐색 문서에서 기본 URI를 가져와야 합니다. 다음 설명에서는 기본 URI가 https://accounts.google.com/o/oauth2/v2/auth이라고 가정합니다.

기본 요청의 경우 다음 매개변수를 지정합니다.

  • client_id: API Console Credentials page에서 가져옵니다.
  • response_type: 기본 승인 코드 흐름 요청에서는 code여야 합니다. (response_type에서 자세히 알아보기)
  • scope: 기본 요청에서는 openid email여야 합니다. (scope에서 자세히 알아보기)
  • redirect_uri는 Google의 응답을 수신할 서버의 HTTP 엔드포인트여야 합니다. 이 값은 API Console Credentials page에서 구성한 OAuth 2.0 클라이언트에 승인된 리디렉션 URI 중 하나와 정확히 일치해야 합니다. 이 값이 승인된 URI와 일치하지 않으면 redirect_uri_mismatch 오류가 발생하여 요청이 실패합니다.
  • state에는 위조 방지 고유 세션 토큰의 값과 사용자가 애플리케이션으로 돌아올 때 컨텍스트를 복구하는 데 필요한 기타 정보(예: 시작 URL)가 포함되어야 합니다. (state에서 자세히 알아보기)
  • nonce는 앱에서 생성한 임의의 값으로, 재생 방지를 사용 설정하면 이 값이 사용됩니다.
  • login_hint는 사용자의 이메일 주소 또는 사용자의 Google ID와 동일한 sub 문자열일 수 있습니다. login_hint를 제공하지 않고 사용자가 현재 로그인되어 있는 경우 동의 화면에 사용자의 이메일 주소를 앱에 공개하기 위한 승인 요청이 포함됩니다. (login_hint에서 자세히 알아보기)
  • hd 매개변수를 사용하여 Google Workspace 또는 Cloud 조직과 연결된 특정 도메인의 사용자를 위해 OpenID Connect 흐름을 최적화합니다 (hd에서 자세히 알아보기).

다음은 가독성을 위해 줄바꿈과 공백이 포함된 전체 OpenID Connect 인증 URI의 예입니다.

https://accounts.google.com/o/oauth2/v2/auth?
 response_type=code&
 client_id=424911365001.apps.googleusercontent.com&
 scope=openid%20email&
 redirect_uri=https%3A//oauth2.example.com/code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2-login-demo.example.com%2FmyHome&
 login_hint=jsmith@example.com&
 nonce=0394852-3190485-2490358&
 hd=example.com

앱에서 사용자에 관한 새로운 정보를 요청하거나 이전에 승인하지 않은 계정 액세스를 요청하는 경우 사용자는 동의해야 합니다.

3. 위조 방지 상태 토큰 확인

응답은 요청에서 지정한 redirect_uri로 전송됩니다. 모든 응답은 아래와 같이 쿼리 문자열로 반환됩니다.

https://oauth2.example.com/code?state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foa2cb.example.com%2FmyHome&code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&scope=openid%20email%20https://www.googleapis.com/auth/userinfo.email

서버에서 Google에서 수신한 state1단계에서 만든 세션 토큰과 일치하는지 확인해야 합니다. 이 왕복 확인은 악의적인 스크립트가 아닌 사용자가 요청을 하고 있는지 확인하는 데 도움이 됩니다.

다음 코드는 1단계에서 만든 세션 토큰을 확인하는 방법을 보여줍니다.

PHP

이 샘플을 사용하려면 PHP용 Google API 클라이언트 라이브러리를 다운로드해야 합니다.

// Ensure that there is no request forgery going on, and that the user
// sending us this connect request is the user that was supposed to.
if ($request->get('state') != ($app['session']->get('state'))) {
  return new Response('Invalid state parameter', 401);
}

자바

이 샘플을 사용하려면 Java용 Google API 클라이언트 라이브러리를 다운로드해야 합니다.

// Ensure that there is no request forgery going on, and that the user
// sending us this connect request is the user that was supposed to.
if (!request.queryParams("state").equals(
    request.session().attribute("state"))) {
  response.status(401);
  return GSON.toJson("Invalid state parameter.");
}

Python

이 샘플을 사용하려면 Python용 Google API 클라이언트 라이브러리를 다운로드해야 합니다.

# Ensure that the request is not a forgery and that the user sending
# this connect request is the expected user.
if request.args.get('state', '') != session['state']:
  response = make_response(json.dumps('Invalid state parameter.'), 401)
  response.headers['Content-Type'] = 'application/json'
  return response

4. code를 액세스 토큰 및 ID 토큰으로 교환

응답에는 서버가 액세스 토큰과 ID 토큰으로 교환할 수 있는 일회성 인증 코드인 code 매개변수가 포함됩니다. 서버는 HTTPS POST 요청을 전송하여 이 교환을 실행합니다. POST 요청은 토큰 엔드포인트로 전송되며, 이 엔드포인트는 token_endpoint 메타데이터 값을 사용하여 탐색 문서에서 가져와야 합니다. 다음 설명에서는 엔드포인트가 https://oauth2.googleapis.com/token라고 가정합니다. 요청의 POST 본문에는 다음 매개변수가 포함되어야 합니다.

필드
code 초기 요청에서 반환된 승인 코드입니다.
client_id OAuth 2.0 사용자 인증 정보 가져오기에 설명된 대로 API Console Credentials page에서 가져온 클라이언트 ID입니다.
client_secret OAuth 2.0 사용자 인증 정보 가져오기에 설명된 대로 API Console Credentials page에서 가져온 클라이언트 보안 비밀번호입니다.
redirect_uri 리디렉션 URI 설정에 설명된 대로 API Console Credentials page에 지정된 지정된 client_id의 승인된 리디렉션 URI입니다.
grant_type 이 필드는 OAuth 2.0 사양에 정의된 대로 authorization_code 값을 포함해야 합니다.

실제 요청은 다음 예와 같습니다.

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your-client-id&
client_secret=your-client-secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code

이 요청에 대한 성공적인 응답에는 JSON 배열에 다음 필드가 포함됩니다.

필드
access_token Google API로 전송할 수 있는 토큰입니다.
expires_in 액세스 토큰의 남은 수명(초)입니다.
id_token Google에서 디지털 서명한 사용자의 ID 정보가 포함된 JWT입니다.
scope access_token에서 부여한 액세스 범위로, 공백으로 구분되고 대소문자가 구분되는 문자열 목록으로 표현됩니다.
token_type 반환된 토큰의 유형을 식별합니다. 이 시점에서 이 필드의 값은 항상 Bearer입니다.
refresh_token (선택사항)

이 필드는 인증 요청에서 access_type 매개변수가 offline로 설정된 경우에만 표시됩니다. 자세한 내용은 갱신 토큰을 참고하세요.

5. ID 토큰에서 사용자 정보 가져오기

ID 토큰은 JWT(JSON 웹 토큰) 즉, 암호화 서명된 Base64 인코딩 JSON 객체입니다. 일반적으로 ID 토큰을 사용하기 전에 ID 토큰을 확인하는 것이 중요하지만, 중개자 없는 HTTPS 채널을 통해 Google과 직접 통신하고 클라이언트 비밀번호를 사용하여 Google에 인증하므로 수신한 토큰이 실제로 Google에서 발급한 유효한 토큰이라고 확신할 수 있습니다. 서버가 ID 토큰을 앱의 다른 구성요소에 전달하는 경우 다른 구성요소가 토큰을 사용하기 전에 토큰을 유효성 검사하는 것이 매우 중요합니다.

대부분의 API 라이브러리는 유효성 검사를 base64url 인코딩된 값을 디코딩하고 내부의 JSON을 파싱하는 작업과 결합하므로 ID 토큰의 클레임에 액세스할 때 어쨌든 토큰을 유효성 검사하게 됩니다.

ID 토큰의 페이로드

ID 토큰은 이름/값 쌍 집합을 포함하는 JSON 객체입니다. 다음은 가독성을 위해 형식이 지정된 예시입니다.

{
  "iss": "https://accounts.google.com",
  "azp": "1234987819200.apps.googleusercontent.com",
  "aud": "1234987819200.apps.googleusercontent.com",
  "sub": "10769150350006150715113082367",
  "at_hash": "HK6E_P6Dh8Y93mRNtsDB1Q",
  "hd": "example.com",
  "email": "jsmith@example.com",
  "email_verified": "true",
  "iat": 1353601026,
  "exp": 1353604926,
  "nonce": "0394852-3190485-2490358"
}

Google ID 토큰에는 수취라고 하는 다음 필드가 포함될 수 있습니다.

소유권 주장 제공 설명
aud 항상 이 ID 토큰의 대상입니다. 애플리케이션의 OAuth 2.0 클라이언트 ID 중 하나여야 합니다.
exp 항상 ID 토큰이 허용되지 않는 만료 시간입니다. Unix 시간 (정수 초)으로 표시됩니다.
iat 항상 ID 토큰이 발급된 시간입니다. Unix 시간 (정수 초)으로 표시됩니다.
iss 항상 응답의 발급기관 식별자입니다. Google ID 토큰의 경우 항상 https://accounts.google.com 또는 accounts.google.com입니다.
sub 항상 사용자의 식별자로, 모든 Google 계정에서 고유하며 재사용되지 않습니다. Google 계정은 서로 다른 시점에 여러 이메일 주소를 가질 수 있지만 sub 값은 변경되지 않습니다. 애플리케이션 내에서 sub를 사용자의 고유 식별자 키로 사용하세요. 대소문자를 구분하는 ASCII 문자 최대 255자(영문 기준)
at_hash 액세스 토큰 해시 액세스 토큰이 ID 토큰에 연결되어 있는지 확인합니다. 서버 흐름에서 ID 토큰이 access_token 값으로 발급되면 이 클레임은 항상 포함됩니다. 이 클레임은 교차 사이트 요청 위조 공격을 방지하기 위한 대체 메커니즘으로 사용할 수 있지만 1단계3단계를 따르는 경우 액세스 토큰을 확인할 필요가 없습니다.
azp 승인된 발표자의 client_id입니다. 이 클레임은 ID 토큰을 요청하는 당사자가 ID 토큰의 대상과 다른 경우에만 필요합니다. Google에서 웹 애플리케이션과 Android 앱이 OAuth 2.0 client_id는 서로 다르지만 동일한 Google API 프로젝트를 공유하는 하이브리드 앱이 여기에 해당할 수 있습니다.
email 사용자의 이메일 주소 요청에 email 범위를 포함한 경우에만 제공됩니다. 이 소유권 주장의 값은 이 계정에 고유하지 않을 수 있으며 시간이 지남에 따라 변경될 수 있으므로 이 값을 사용자 레코드에 연결하는 기본 식별자로 사용해서는 안 됩니다. 또한 email 클레임의 도메인을 사용하여 Google Workspace 또는 Cloud 조직의 사용자를 식별할 수 없습니다. 대신 hd 클레임을 사용하세요.
email_verified 사용자의 이메일 주소가 확인된 경우 true입니다. 그렇지 않으면 false를 반환합니다.
family_name 사용자의 성입니다. name 소유권 주장이 있는 경우 제공될 수 있습니다.
given_name 사용자의 이름 또는 이름입니다. name 소유권 주장이 있는 경우 제공될 수 있습니다.
hd 사용자의 Google Workspace 또는 Cloud 조직과 연결된 도메인입니다. 사용자가 Google Cloud 조직에 속한 경우에만 제공됩니다. 리소스에 대한 액세스를 특정 도메인의 구성원에게만 제한하는 경우 이 소유권 주장을 선택해야 합니다. 이 클레임이 없으면 계정이 Google 호스팅 도메인에 속하지 않음을 나타냅니다.
locale BCP 47 언어 태그로 표시되는 사용자의 언어입니다. name 소유권 주장이 있는 경우 제공될 수 있습니다.
name 표시 가능한 형식으로 된 사용자의 전체 이름입니다. 다음과 같은 경우에 제공될 수 있습니다.
  • 요청 범위에 '프로필' 문자열이 포함됨
  • ID 토큰이 토큰 갱신에서 반환됨

name 클레임이 있는 경우 이를 사용하여 앱의 사용자 레코드를 업데이트할 수 있습니다. 이 소유권 주장이 항상 표시되는 것은 아닙니다.

nonce 인증 요청에서 앱이 제공하는 nonce 값입니다. 한 번만 표시되도록 하여 재전송 공격으로부터 보호해야 합니다.
picture 사용자 프로필 사진의 URL입니다. 다음과 같은 경우에 제공될 수 있습니다.
  • 요청 범위에 '프로필' 문자열이 포함됨
  • ID 토큰이 토큰 갱신에서 반환됨

picture 소유권 주장이 있는 경우 이를 사용하여 앱의 사용자 레코드를 업데이트할 수 있습니다. 이 소유권 주장이 항상 표시되는 것은 아닙니다.

profile 사용자의 프로필 페이지 URL입니다. 다음과 같은 경우에 제공될 수 있습니다.
  • 요청 범위에 '프로필' 문자열이 포함됨
  • ID 토큰이 토큰 갱신에서 반환됨

profile 소유권 주장이 있는 경우 이를 사용하여 앱의 사용자 레코드를 업데이트할 수 있습니다. 이 소유권 주장이 항상 표시되는 것은 아닙니다.

6. 사용자 인증

ID 토큰에서 사용자 정보를 가져온 후에는 앱의 사용자 데이터베이스를 쿼리해야 합니다. 사용자가 이미 데이터베이스에 있는 경우 Google API 응답에서 모든 로그인 요구사항이 충족되면 해당 사용자의 애플리케이션 세션을 시작해야 합니다.

사용자가 사용자 데이터베이스에 없는 경우 사용자를 신규 사용자 가입 흐름으로 리디렉션해야 합니다. Google에서 수신한 정보를 기반으로 사용자를 자동 등록하거나 최소한 등록 양식에 필요한 대부분의 입력란을 미리 채울 수 있습니다. ID 토큰의 정보 외에도 사용자 프로필 엔드포인트에서 추가 사용자 프로필 정보를 가져올 수 있습니다.

고급 주제

다음 섹션에서는 Google OAuth 2.0 API를 자세히 설명합니다. 이 정보는 인증 및 승인과 관련하여 고급 요구사항이 있는 개발자를 위해 작성되었습니다.

다른 Google API 액세스

인증에 OAuth 2.0을 사용하는 이점 중 하나는 애플리케이션이 사용자를 인증하는 동시에 사용자를 대신하여 다른 Google API (예: YouTube, Google Drive, Calendar, 연락처)를 사용할 권한을 얻을 수 있다는 것입니다. 이렇게 하려면 Google에 전송하는 인증 요청에 필요한 다른 범위를 포함합니다. 예를 들어 인증 요청에 사용자의 연령대를 추가하려면 openid email https://www.googleapis.com/auth/profile.agerange.read의 범위 매개변수를 전달합니다. 동의 화면에 사용자에게 적절한 메시지가 표시됩니다. Google에서 반환하는 액세스 토큰을 사용하면 요청하고 부여받은 액세스 범위와 관련된 모든 API에 액세스할 수 있습니다.

갱신 토큰

API 액세스 요청에서 code 교환 중에 반환할 갱신 토큰을 요청할 수 있습니다. 갱신 토큰은 사용자가 애플리케이션에 없을 때 앱이 Google API에 계속 액세스할 수 있도록 합니다. 새로고침 토큰을 요청하려면 인증 요청에서 access_type 매개변수를 offline로 설정합니다.

고려사항:

  • 갱신 토큰은 코드 교환 흐름을 처음 실행할 때만 가져올 수 있으므로 갱신 토큰을 안전하고 영구적으로 저장해야 합니다.
  • 발급되는 새로고침 토큰 수에는 한도가 있습니다. 클라이언트/사용자 조합당 한도와 모든 클라이언트에서 사용자당 한도가 있습니다. 애플리케이션에서 새로고침 토큰을 너무 많이 요청하면 이러한 제한이 발생할 수 있으며, 이 경우 이전 새로고침 토큰이 작동을 멈춥니다.

자세한 내용은 액세스 토큰 갱신(오프라인 액세스)을 참고하세요.

인증 요청에서 prompt 매개변수를 consent로 설정하여 사용자에게 앱을 재승인하라는 메시지를 표시할 수 있습니다. prompt=consent가 포함된 경우 이전에 모든 범위가 Google API 프로젝트에 부여되었더라도 앱이 액세스 범위 승인을 요청할 때마다 동의 화면이 표시됩니다. 따라서 필요한 경우에만 prompt=consent를 포함하세요.

prompt 매개변수에 관한 자세한 내용은 인증 URI 매개변수 표의 prompt를 참고하세요.

인증 URI 매개변수

다음 표에서는 Google의 OAuth 2.0 인증 API에서 허용하는 매개변수에 대해 더 자세히 설명합니다.

매개변수 필수 설명
client_id (필수) OAuth 2.0 사용자 인증 정보 가져오기에 설명된 대로 API Console Credentials page에서 가져온 클라이언트 ID 문자열입니다.
nonce (필수) 재전송 방지를 사용 설정하는 앱에서 생성한 임의 값입니다.
response_type (필수) 값이 code이면 기본 승인 코드 흐름을 실행하며, 토큰을 얻으려면 토큰 엔드포인트에 POST가 필요합니다. 값이 token id_token 또는 id_token token이면 암시적 흐름을 시작합니다. 이 경우 리디렉션 URI에서 JavaScript를 사용하여 URI #fragment 식별자에서 토큰을 가져와야 합니다.
redirect_uri (필수) 응답을 보낼 위치를 결정합니다. 이 매개변수의 값은 API Console Credentials page 에 설정된 승인된 리디렉션 값 중 하나와 정확히 일치해야 합니다(HTTP 또는 HTTPS 스키마, 대소문자, 뒤의 '/' 포함).
scope (필수)

범위 매개변수는 openid 값으로 시작하고 profile 값, email 값 또는 둘 다를 포함해야 합니다.

profile 범위 값이 있는 경우 ID 토큰에 사용자의 기본 profile 클레임이 포함될 수 있지만 보장되지는 않습니다.

email 범위 값이 있는 경우 ID 토큰에 emailemail_verified 클레임이 포함됩니다.

이러한 OpenID별 범위 외에도 범위 인수에 다른 범위 값을 포함할 수도 있습니다. 모든 범위 값은 공백으로 구분해야 합니다. 예를 들어 사용자의 Google Drive에 파일별로 액세스하려는 경우 범위 매개변수는 openid profile email https://www.googleapis.com/auth/drive.file일 수 있습니다.

사용 가능한 범위에 관한 자세한 내용은 Google API용 OAuth 2.0 범위 또는 사용하려는 Google API의 문서를 참고하세요.

state (선택사항이지만 적극 권장됨)

프로토콜에서 왕복되는 불투명 문자열입니다. 즉, 기본 흐름에서는 URI 매개변수로, 암시적 흐름에서는 URI #fragment 식별자로 반환됩니다.

state는 요청과 응답을 연결하는 데 유용할 수 있습니다. redirect_uri는 추측할 수 있으므로 state 값을 사용하면 수신 연결이 앱에서 시작한 인증 요청의 결과라는 확신을 높일 수 있습니다. 이 state 변수에 무작위 문자열을 생성하거나 일부 클라이언트 상태 (예: 쿠키)의 해시를 인코딩하면 응답을 검증하여 요청과 응답이 동일한 브라우저에서 발생했는지 추가로 확인할 수 있습니다. 이렇게 하면 크로스 사이트 요청 위조와 같은 공격으로부터 보호할 수 있습니다.

access_type (선택사항) 허용되는 값은 offlineonline입니다. 이 효과는 오프라인 액세스에 설명되어 있습니다. 액세스 토큰이 요청되는 경우 offline 값이 지정되지 않으면 클라이언트는 갱신 토큰을 수신하지 않습니다.
display (선택사항) 승인 서버가 인증 및 동의 사용자 인터페이스 페이지를 표시하는 방법을 지정하는 ASCII 문자열 값입니다. 다음 값은 지정되고 Google 서버에서 허용되지만 동작에 영향을 미치지 않습니다. page, popup, touch, wap
hd (선택사항)

Google Cloud 조직에서 소유한 계정의 로그인 절차를 간소화합니다. Google Cloud 조직 도메인 (예: mycollege.edu)을 포함하면 계정 선택 UI가 해당 도메인의 계정에 맞게 최적화되어야 함을 나타낼 수 있습니다. 하나의 Google Cloud 조직 도메인 대신 일반적으로 Google Cloud 조직 계정에 맞게 최적화하려면 별표 (*) 값을 설정합니다. hd=*

클라이언트 측 요청을 수정할 수 있으므로 이 UI 최적화를 사용하여 앱에 액세스할 수 있는 사용자를 제어하지 마세요. 반환된 ID 토큰에 예상한 값 (예: mycolledge.edu)과 일치하는 hd 클레임 값이 있는지 유효성 검사해야 합니다. 요청 매개변수와 달리 ID 토큰 hd 클레임은 Google의 보안 토큰 내에 포함되어 있으므로 값을 신뢰할 수 있습니다.

include_granted_scopes (선택사항) 이 매개변수에 true 값이 제공되고 승인 요청이 승인되면 이 사용자/애플리케이션 조합에 다른 범위에서 부여된 이전 승인이 승인에 포함됩니다. 증분 승인을 참고하세요.

설치된 앱 흐름으로는 증분 승인을 수행할 수 없습니다.

login_hint (선택사항) 앱에서 인증하려는 사용자를 알고 있으면 이 매개변수를 인증 서버에 힌트로 제공할 수 있습니다. 이 힌트를 전달하면 계정 선택기가 숨겨지고 로그인 양식의 이메일 상자가 자동으로 채워지거나 적절한 세션이 선택됩니다 (사용자가 다중 로그인을 사용하는 경우). 이렇게 하면 앱이 잘못된 사용자 계정에 로그인할 때 발생하는 문제를 방지할 수 있습니다. 값은 이메일 주소 또는 사용자의 Google ID와 동일한 sub 문자열일 수 있습니다.
prompt (선택사항) 승인 서버에서 사용자에게 재인증 및 동의 메시지를 표시할지 지정하는 공백으로 구분된 문자열 값 목록입니다. 가능한 값은 다음과 같습니다.
  • none

    승인 서버는 인증 또는 사용자 동의 화면을 표시하지 않습니다. 사용자가 아직 인증되지 않았거나 요청된 범위에 대한 동의를 사전 구성하지 않은 경우 오류가 반환됩니다. none를 사용하여 기존 인증 또는 동의를 확인할 수 있습니다.

  • consent

    승인 서버는 클라이언트에 정보를 반환하기 전에 사용자에게 동의 메시지를 표시합니다.

  • select_account

    승인 서버에서 사용자에게 사용자 계정을 선택하라는 메시지를 표시합니다. 이렇게 하면 승인 서버에 여러 계정이 있는 사용자가 현재 세션이 있을 수 있는 여러 계정 중에서 선택할 수 있습니다.

값을 지정하지 않았고 사용자가 이전에 액세스를 승인하지 않은 경우 사용자에게 동의 화면이 표시됩니다.

ID 토큰 유효성 검사

ID 토큰이 Google에서 직접 전송된 것으로 알고 있는 경우가 아니라면 서버에서 모든 ID 토큰의 유효성을 검사해야 합니다. 예를 들어 서버는 클라이언트 앱에서 수신한 ID 토큰을 진짜인지 확인해야 합니다.

다음은 ID 토큰을 서버로 전송할 수 있는 일반적인 상황입니다.

  • 인증이 필요한 요청과 함께 ID 토큰을 전송합니다. ID 토큰은 요청을 한 특정 사용자와 ID 토큰이 부여된 클라이언트를 알려줍니다.

ID 토큰은 민감하며 가로채면 악용될 수 있습니다. 이러한 토큰은 HTTPS를 통해서만, POST 데이터를 통해서만 또는 요청 헤더 내에서만 전송하여 안전하게 처리해야 합니다. 서버에 ID 토큰을 저장하는 경우에도 안전하게 저장해야 합니다.

ID 토큰을 유용하게 만드는 한 가지 이유는 앱의 여러 구성요소 간에 전달할 수 있다는 점입니다. 이러한 구성요소는 ID 토큰을 앱과 사용자를 인증하는 경량 인증 메커니즘으로 사용할 수 있습니다. 하지만 ID 토큰의 정보를 사용하거나 사용자가 인증했다는 어설션으로 사용하려면 먼저 유효성을 검사해야 합니다.

ID 토큰을 검증하려면 다음과 같은 여러 단계를 거쳐야 합니다.

  1. ID 토큰에 발급자가 올바르게 서명했는지 확인합니다. Google에서 발급한 토큰은 검색 문서jwks_uri 메타데이터 값에 지정된 URI에 있는 인증서 중 하나를 사용하여 서명됩니다.
  2. ID 토큰의 iss 클레임 값이 https://accounts.google.com 또는 accounts.google.com와 같은지 확인합니다.
  3. ID 토큰의 aud 클레임 값이 앱의 클라이언트 ID와 같은지 확인합니다.
  4. ID 토큰의 만료 시간 (exp 클레임)이 지났는지 확인합니다.
  5. 요청에 hd 매개변수 값을 지정한 경우 ID 토큰에 Google Cloud 조직과 연결된 허용된 도메인과 일치하는 hd 클레임이 있는지 확인합니다.

2~5단계는 문자열 및 날짜 비교만 포함되며 비교는 매우 간단하므로 여기서는 자세히 설명하지 않습니다.

첫 번째 단계는 더 복잡하며 암호화 서명 검사가 포함됩니다. 디버깅을 위해 Google의 tokeninfo 엔드포인트를 사용하여 서버 또는 기기에 구현된 로컬 처리와 비교할 수 있습니다. ID 토큰의 값이 XYZ123이라고 가정해 보겠습니다. 그런 다음 URI https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123의 참조를 해제합니다. 토큰 서명이 유효하면 응답은 디코딩된 JSON 객체 형식의 JWT 페이로드가 됩니다.

tokeninfo 엔드포인트는 디버깅에 유용하지만 프로덕션 목적으로는 키 엔드포인트에서 Google의 공개 키를 가져와 로컬에서 유효성 검사를 실행하세요. jwks_uri 메타데이터 값을 사용하여 탐색 문서에서 키 URI를 가져와야 합니다. 디버깅 엔드포인트의 요청이 제한되거나 간헐적인 오류가 발생할 수 있습니다.

Google은 공개 키를 자주 변경하지 않으므로 HTTP 응답의 캐시 지시어를 사용하여 공개 키를 캐시할 수 있으며, 대부분의 경우 tokeninfo 엔드포인트를 사용하는 것보다 훨씬 더 효율적으로 로컬 유효성 검사를 실행할 수 있습니다. 이 유효성 검사를 위해서는 인증서를 검색하고 파싱하고 적절한 암호화 호출을 실행하여 서명을 확인해야 합니다. 다행히 이를 실행할 수 있는 다양한 언어로 된 잘 디버그된 라이브러리가 있습니다 (jwt.io 참고).

사용자 프로필 정보 가져오기

사용자에 관한 추가 프로필 정보를 얻으려면 액세스 토큰(애플리케이션이 인증 흐름 중에 수신함)과 OpenID Connect 표준을 사용하면 됩니다.

  1. OpenID를 준수하려면 인증 요청openid profile 범위 값을 포함해야 합니다.

    사용자의 이메일 주소를 포함하려면 추가 범위 값 email를 지정하면 됩니다. profileemail를 모두 지정하려면 인증 요청 URI에 다음 매개변수를 포함하면 됩니다.

    scope=openid%20profile%20email
  2. 액세스 토큰을 인증 헤더에 추가하고 userinfo 엔드포인트에 HTTPS GET 요청을 보냅니다. 이 엔드포인트는 userinfo_endpoint 메타데이터 값을 사용하여 탐색 문서에서 가져와야 합니다. userinfo 응답에는 OpenID Connect Standard Claims에 설명된 대로 사용자에 관한 정보와 탐색 문서의 claims_supported 메타데이터 값이 포함됩니다. 사용자 또는 사용자의 조직에서 특정 입력란을 제공하거나 제공하지 않을 수 있으므로 승인된 액세스 범위의 모든 입력란에 대한 정보를 가져오지 못할 수 있습니다.

탐색 문서

OpenID Connect 프로토콜에서는 사용자를 인증하고 토큰, 사용자 정보, 공개 키를 비롯한 리소스를 요청하기 위해 여러 엔드포인트를 사용해야 합니다.

구현을 간소화하고 유연성을 높이기 위해 OpenID Connect에서는 '검색 문서'를 사용할 수 있습니다. 검색 문서는 잘 알려진 위치에 있는 JSON 문서이며, 인증, 토큰, 취소, 사용자 정보, 공개 키 엔드포인트의 URI를 비롯하여 OpenID Connect 제공업체의 구성에 관한 세부정보를 제공하는 키-값 쌍을 포함합니다. Google의 OpenID Connect 서비스에 대한 탐색 문서는 다음 위치에서 가져올 수 있습니다.

https://accounts.google.com/.well-known/openid-configuration

Google의 OpenID Connect 서비스를 사용하려면 검색 문서 URI(https://accounts.google.com/.well-known/openid-configuration)를 애플리케이션에 하드코딩해야 합니다. 애플리케이션은 문서를 가져와 응답에 캐싱 규칙을 적용한 후 필요에 따라 문서에서 엔드포인트 URI를 검색합니다. 예를 들어 사용자를 인증하기 위해 코드는 authorization_endpoint 메타데이터 값(아래 예에서는 https://accounts.google.com/o/oauth2/v2/auth)을 Google에 전송되는 인증 요청의 기본 URI로 가져옵니다.

다음은 이러한 문서의 예입니다. 필드 이름은 OpenID Connect Discovery 1.0에 지정된 이름입니다(의미는 해당 문서 참고). 이 값은 실제 Google 디스커버리 문서의 최신 버전에서 복사되었지만 참고용일 뿐이며 변경될 수 있습니다.

{
  "issuer": "https://accounts.google.com",
  "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
  "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
  "token_endpoint": "https://oauth2.googleapis.com/token",
  "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
  "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
  "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
  "response_types_supported": [
    "code",
    "token",
    "id_token",
    "code token",
    "code id_token",
    "token id_token",
    "code token id_token",
    "none"
  ],
  "subject_types_supported": [
    "public"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "scopes_supported": [
    "openid",
    "email",
    "profile"
  ],
  "token_endpoint_auth_methods_supported": [
    "client_secret_post",
    "client_secret_basic"
  ],
  "claims_supported": [
    "aud",
    "email",
    "email_verified",
    "exp",
    "family_name",
    "given_name",
    "iat",
    "iss",
    "locale",
    "name",
    "picture",
    "sub"
  ],
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ]
}

검색 문서의 값을 캐시하여 HTTP 왕복을 피할 수 있습니다. 표준 HTTP 캐싱 헤더가 사용되며 이를 준수해야 합니다.

클라이언트 라이브러리

다음 클라이언트 라이브러리는 널리 사용되는 프레임워크와 통합하여 OAuth 2.0을 더 간편하게 구현할 수 있도록 지원합니다.

OpenID Connect 규정 준수

Google의 OAuth 2.0 인증 시스템은 OpenID Connect Core 사양의 필수 기능을 지원합니다. OpenID Connect와 함께 작동하도록 설계된 모든 클라이언트는 이 서비스와 상호 운용되어야 합니다(OpenID 요청 객체 제외).