OAuth 및 Google 로그인을 사용한 간소화된 연결

개요

OAuth 기반 Google 로그인 간소화 연결OAuth 연결 외에 Google 로그인을 추가합니다. 이를 통해 Google 사용자에게 원활한 연결 환경이 제공되며 사용자가 Google 계정을 사용하여 서비스에 새 계정을 만들 수 있는 계정 생성도 가능합니다.

OAuth 및 Google 로그인을 사용하여 계정을 연결하려면 다음 일반 단계를 따르세요.

  1. 먼저 사용자에게 Google 프로필 액세스에 동의해 달라고 요청합니다.
  2. 프로필에 있는 정보를 사용하여 사용자 계정이 존재하는지 확인합니다.
  3. 기존 사용자의 경우 계정을 연결합니다.
  4. 인증 시스템에서 Google 사용자와 일치하는 결과를 찾을 수 없는 경우 Google에서 받은 ID 토큰을 검증하세요. 그러면 ID 토큰에 포함된 프로필 정보를 기반으로 사용자를 만들 수 있습니다.
이 그림은 사용자가 간소화된 연결 흐름을 사용하여 Google 계정을 연결하는 단계를 보여줍니다. 첫 번째 스크린샷은 사용자가 연결할 앱을 선택하는 방법을 보여줍니다. 두 번째 스크린샷을 통해 사용자는 서비스에 기존 계정이 있는지 확인할 수 있습니다. 세 번째 스크린샷을 통해 사용자는 연결할 Google 계정을 선택할 수 있습니다. 네 번째 스크린샷은 Google 계정을 앱과 연결하기 위한 확인입니다. 다섯 번째 스크린샷은 Google 앱에서 성공적으로 연결된 사용자 계정을 보여줍니다.

그림 1. 간소화된 연결을 통한 사용자 휴대전화의 계정 연결

간소화된 연결을 위한 요구사항

  • 기본 웹 OAuth 연결 흐름을 구현합니다. 서비스에서 OAuth 2.0을 준수하는 승인토큰 교환 엔드포인트를 지원해야 합니다.
  • 토큰 교환 엔드포인트는 JSON 웹 토큰 (JWT) 어설션을 지원하고 check, create, get 인텐트를 구현해야 합니다.

OAuth 서버 구현

토큰 교환 엔드포인트는 check, create, get 인텐트를 지원해야 합니다. 다음은 계정 연결 흐름을 통해 완료된 단계와 서로 다른 인텐트가 호출되는 시점을 보여줍니다.

  1. 사용자의 인증 시스템에 계정이 있나요? (사용자가 '예' 또는 '아니요'를 선택하여 결정)
    1. 예 : 사용자가 Google 계정과 연결된 이메일을 사용하여 플랫폼에 로그인하나요? (사용자가 '예' 또는 '아니요'를 선택하여 결정)
      1. 예 : 사용자의 인증 시스템에 일치하는 계정이 있나요? (check intent가 호출되어 확인)
        1. 예: get intent가 호출되고 가져오기 인텐트가 성공적으로 반환되면 계정이 연결됩니다.
        2. 아니요 : 새 계정을 만드시겠습니까? (사용자가 '예' 또는 '아니요'를 선택하여 결정)
          1. 예 : create intent가 호출되고 생성 인텐트가 성공적으로 반환되면 계정이 연결됩니다.
          2. 아니요 : 웹 OAuth 흐름이 트리거되고 사용자는 브라우저로 이동되며 사용자에게 다른 이메일과 연결할 수 있는 옵션이 제공됩니다.
      2. 아니요 : 웹 OAuth 흐름이 트리거되고 사용자가 사용 중인 브라우저로 이동되며 사용자에게 다른 이메일과 연결할 수 있는 옵션이 제공됩니다.
    2. 아니요 : 사용자의 인증 시스템에 일치하는 계정이 있나요? (check intent가 호출되어 확인)
      1. 예 : get intent가 호출되고 가져오기 인텐트가 성공적으로 반환되면 계정이 연결됩니다.
      2. 아니요: create intent가 호출되고 생성 인텐트가 성공적으로 반환되면 계정이 연결됩니다.

检查现有用户帐号(检查 intent)

在用户同意访问其 Google 个人资料后,Google 会发送一个请求,其中包含 Google 用户身份的签名断言。该断言包含用户的 Google 帐号 ID、姓名和电子邮件地址。为您的项目配置的令牌交换端点会处理该请求。

如果您的身份验证系统中已存在相应的 Google 帐号,则您的令牌交换端点会返回 account_found=true。如果 Google 帐号与现有用户不匹配,那么您的令牌交换端点会返回 account_found=false 的 HTTP 404 Not Found 错误。

请求的格式如下:

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

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=check&assertion=JWT&scope=SCOPES&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

您的令牌交换端点必须能够处理以下参数:

令牌端点参数
intent 对于这些请求,此参数的值为 check
grant_type 要交换的令牌的类型。对于这些请求,此参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer
assertion 一个 JSON Web 令牌 (JWT),用于提供 Google 用户身份的签名断言。JWT 包含用户的 Google 帐号 ID、姓名和电子邮件地址等信息。
client_id 您分配给 Google 的客户端 ID。
client_secret 您分配给 Google 的客户端密钥。

为了响应 check intent 请求,您的令牌交换端点必须执行以下步骤:

  • 验证并解码 JWT 断言。
  • 检查您的身份验证系统中是否已存在该 Google 帐号。
JWT 어설 션 유효성 검사 및 디코딩

해당 언어에 대한 JWT 디코딩 라이브러리를 사용하여 JWT 어설 션의 유효성을 검사하고 디코딩 할 수 있습니다 . JWK 또는 PEM 형식으로 제공되는 Google의 공개 키를 사용하여 토큰의 서명을 확인합니다.

디코딩 될 때 JWT 어설 션은 다음 예제와 같습니다.

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

토큰의 서명을 확인하는 것 외에도 어설 션의 발급자 ( iss 필드)가 https://accounts.google.com 이고 대상 ( aud 필드)이 할당 된 클라이언트 ID이며 토큰이 만료되지 않았는지 ( exp 들).

email , email_verifiedhd 필드를 사용하여 Google이 이메일 주소를 호스팅하고 권한이 있는지 확인할 수 있습니다. Google이 권한이있는 경우 사용자는 현재 합법적 인 계정 소유자로 알려져 있으며 비밀번호 또는 기타 질문 방법을 건너 뛸 수 있습니다. 그렇지 않으면 이러한 방법을 사용하여 연결하기 전에 계정을 확인할 수 있습니다.

Google이 권위있는 사례 :

  • email 에는 @gmail.com 접미사가 있으며 이는 Gmail 계정입니다.
  • email_verified 가 true이고 hd 가 설정되어있는 G Suite 계정입니다.

사용자는 Gmail 또는 G Suite를 사용하지 않고 Google 계정에 등록 할 수 있습니다. email@gmail.com 접미사가없고 hd 가없는 경우 Google은 신뢰할 수 없으며 사용자를 확인하기 위해 비밀번호 또는 다른 질문 방법을 사용하는 것이 좋습니다. email_verfied 는 Google 계정이 생성 될 때 Google이 처음에 사용자를 확인 email_verfied true 일 수도 있지만 이후 타사 이메일 계정의 소유권이 변경되었을 수 있습니다.

检查您的身份验证系统中是否已存在该 Google 帐号

检查是否满足以下任一条件:

  • Google 帐号 ID 可在用户的数据库中找到,可在断言的 sub 字段找到。
  • 断言中的电子邮件地址与您的用户数据库中的用户匹配。

如果其中任一条件为 true,则表示用户已注册。在这种情况下,系统将返回如下所示的响应:

HTTP/1.1 200 Success
Content-Type: application/json;charset=UTF-8

{
  "account_found":"true",
}

如果断言中指定的 Google 帐号 ID 和电子邮件地址都与用户数据库中的用户不匹配,则表示用户尚未注册。在这种情况下,您的令牌交换端点需要使用包含 "account_found": "false" 的 HTTP 404 错误进行响应,如以下示例所示:

HTTP/1.1 404 Not found
Content-Type: application/json;charset=UTF-8

{
  "account_found":"false",
}

处理自动链接(获取 intent)

在用户同意访问其 Google 个人资料后,Google 会发送一个请求,其中包含 Google 用户身份的签名断言。该断言包含用户的 Google 帐号 ID、姓名和电子邮件地址。为您的项目配置的令牌交换端点会处理该请求。

如果您的身份验证系统中已存在相应的 Google 帐号,则您的令牌交换端点会返回用户的令牌。如果 Google 帐号与现有用户不匹配,您的令牌交换端点会返回 linking_error 错误和可选的 login_hint

请求的格式如下:

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

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=get&assertion=JWT&scope=SCOPES&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

您的令牌交换端点必须能够处理以下参数:

令牌端点参数
intent 对于这些请求,此参数的值为 get
grant_type 要交换的令牌的类型。对于这些请求,此参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer
assertion 一个 JSON Web 令牌 (JWT),用于提供 Google 用户身份的签名断言。JWT 包含用户的 Google 帐号 ID、姓名和电子邮件地址等信息。
scope 可选:您已将 Google 配置为向用户请求的任何范围。
client_id 您分配给 Google 的客户端 ID。
client_secret 您分配给 Google 的客户端密钥。

为了响应 get intent 请求,您的令牌交换端点必须执行以下步骤:

  • 验证并解码 JWT 断言。
  • 检查您的身份验证系统中是否已存在该 Google 帐号。
JWT 어설 션 유효성 검사 및 디코딩

해당 언어에 대한 JWT 디코딩 라이브러리를 사용하여 JWT 어설 션의 유효성을 검사하고 디코딩 할 수 있습니다 . JWK 또는 PEM 형식으로 제공되는 Google의 공개 키를 사용하여 토큰의 서명을 확인합니다.

디코딩 될 때 JWT 어설 션은 다음 예제와 같습니다.

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

토큰의 서명을 확인하는 것 외에도 어설 션의 발급자 ( iss 필드)가 https://accounts.google.com 이고 대상 ( aud 필드)이 할당 된 클라이언트 ID이며 토큰이 만료되지 않았는지 ( exp 들).

email , email_verifiedhd 필드를 사용하여 Google이 이메일 주소를 호스팅하고 권한이 있는지 확인할 수 있습니다. Google이 권한이있는 경우 사용자는 현재 합법적 인 계정 소유자로 알려져 있으며 비밀번호 또는 기타 질문 방법을 건너 뛸 수 있습니다. 그렇지 않으면 이러한 방법을 사용하여 연결하기 전에 계정을 확인할 수 있습니다.

Google이 권위있는 사례 :

  • email 에는 @gmail.com 접미사가 있으며 이는 Gmail 계정입니다.
  • email_verified 가 true이고 hd 가 설정되어있는 G Suite 계정입니다.

사용자는 Gmail 또는 G Suite를 사용하지 않고 Google 계정에 등록 할 수 있습니다. email@gmail.com 접미사가없고 hd 가없는 경우 Google은 신뢰할 수 없으며 사용자를 확인하기 위해 비밀번호 또는 다른 질문 방법을 사용하는 것이 좋습니다. email_verfied 는 Google 계정이 생성 될 때 Google이 처음에 사용자를 확인 email_verfied true 일 수도 있지만 이후 타사 이메일 계정의 소유권이 변경되었을 수 있습니다.

检查您的身份验证系统中是否已存在该 Google 帐号

检查是否满足以下任一条件:

  • Google 帐号 ID 可在用户的数据库中找到,可在断言的 sub 字段找到。
  • 断言中的电子邮件地址与您的用户数据库中的用户匹配。

如果找到了用户的帐号,请发出访问令牌,并在 HTTPS 响应的正文中以 JSON 对象形式返回值,如以下示例所示:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",

  "refresh_token": "REFRESH_TOKEN",

  "expires_in": SECONDS_TO_EXPIRATION
}

在某些情况下,基于 ID 令牌的帐号关联可能会为用户失败。如果出现任何此类情况,您的令牌交换端点都需要使用返回 error=linking_error 的 HTTP 401 错误进行响应,如以下示例所示:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}

Google 收到包含 linking_error 的 401 错误响应后,会将用户作为授权参数 login_hint 发送到您的授权端点。用户在浏览器中使用 OAuth 关联流程完成帐号关联。

通过 Google 登录功能创建帐号(创建 intent)

当用户需要在您的服务上创建帐号时,Google 会向您的令牌交换端点发出请求,并指定 intent=create

请求的格式如下:

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

response_type=token&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&scope=SCOPES&intent=create&assertion=JWT&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

您的令牌交换端点必须能够处理以下参数:

令牌端点参数
intent 对于这些请求,此参数的值为 create
grant_type 要交换的令牌的类型。对于这些请求,此参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer
assertion 一个 JSON Web 令牌 (JWT),用于提供 Google 用户身份的签名断言。JWT 包含用户的 Google 帐号 ID、姓名和电子邮件地址等信息。
client_id 您分配给 Google 的客户端 ID。
client_secret 您分配给 Google 的客户端密钥。

assertion 参数中的 JWT 包含用户的 Google 帐号 ID、名称和电子邮件地址,您可以使用这些信息在服务中创建新帐号。

为了响应 create intent 请求,您的令牌交换端点必须执行以下步骤:

  • 验证并解码 JWT 断言。
  • 验证用户信息并创建新帐号。
JWT 어설 션 유효성 검사 및 디코딩

해당 언어에 대한 JWT 디코딩 라이브러리를 사용하여 JWT 어설 션의 유효성을 검사하고 디코딩 할 수 있습니다 . JWK 또는 PEM 형식으로 제공되는 Google의 공개 키를 사용하여 토큰의 서명을 확인합니다.

디코딩 될 때 JWT 어설 션은 다음 예제와 같습니다.

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

토큰의 서명을 확인하는 것 외에도 어설 션의 발급자 ( iss 필드)가 https://accounts.google.com 이고 대상 ( aud 필드)이 할당 된 클라이언트 ID이며 토큰이 만료되지 않았는지 ( exp 들).

email , email_verifiedhd 필드를 사용하여 Google이 이메일 주소를 호스팅하고 권한이 있는지 확인할 수 있습니다. Google이 권한이있는 경우 사용자는 현재 합법적 인 계정 소유자로 알려져 있으며 비밀번호 또는 기타 질문 방법을 건너 뛸 수 있습니다. 그렇지 않으면 이러한 방법을 사용하여 연결하기 전에 계정을 확인할 수 있습니다.

Google이 권위있는 사례 :

  • email 에는 @gmail.com 접미사가 있으며 이는 Gmail 계정입니다.
  • email_verified 가 true이고 hd 가 설정되어있는 G Suite 계정입니다.

사용자는 Gmail 또는 G Suite를 사용하지 않고 Google 계정에 등록 할 수 있습니다. email@gmail.com 접미사가없고 hd 가없는 경우 Google은 신뢰할 수 없으며 사용자를 확인하기 위해 비밀번호 또는 다른 질문 방법을 사용하는 것이 좋습니다. email_verfied 는 Google 계정이 생성 될 때 Google이 처음에 사용자를 확인 email_verfied true 일 수도 있지만 이후 타사 이메일 계정의 소유권이 변경되었을 수 있습니다.

验证用户信息并创建新帐号

检查是否满足以下任一条件:

  • Google 帐号 ID 可在用户的数据库中找到,可在断言的 sub 字段找到。
  • 断言中的电子邮件地址与您的用户数据库中的用户匹配。

如果任一条件为 true,请提示用户将其现有帐号与其 Google 帐号相关联。为此,请对请求进行响应,并提供指定 error=linking_error 并将用户的电子邮件地址作为 login_hint 的 HTTP 401 错误。以下是一个示例响应:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}

Google 收到包含 linking_error 的 401 错误响应后,会将用户作为授权参数 login_hint 发送到您的授权端点。用户在浏览器中使用 OAuth 关联流程完成帐号关联。

如果两个条件都不满足,请使用 JWT 中提供的信息创建新的用户帐号。新帐号通常不会设置密码。建议您将 Google 登录功能添加到其他平台,以便用户能够在应用界面使用 Google 帐号登录。或者,您也可以通过电子邮件向用户发送一个启动密码恢复流程的链接,以便用户设置密码以在其他平台上登录。

创建完成后,发出访问令牌 和刷新令牌 ,并在 HTTPS 响应的正文中以 JSON 对象形式返回值,如以下示例所示:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",

  "refresh_token": "REFRESH_TOKEN",

  "expires_in": SECONDS_TO_EXPIRATION
}

Google API 클라이언트 ID 가져오기

계정 연결 등록 과정 중에 Google API 클라이언트 ID를 제공해야 합니다.

OAuth 연결 단계를 완료하는 동안 만든 프로젝트를 사용하여 API 클라이언트 ID를 가져옵니다. 그러려면 다음 단계를 완료하세요.

  1. Google API 콘솔사용자 인증 정보 페이지를 엽니다.
  2. Google API 프로젝트를 만들거나 선택합니다.

    프로젝트에 웹 애플리케이션 유형의 클라이언트 ID가 없으면 사용자 인증 정보 만들기 > OAuth 클라이언트 ID를 클릭하여 클라이언트 ID를 만듭니다. 승인된 자바스크립트 원본 상자에 사이트의 도메인을 포함해야 합니다. 로컬 테스트 또는 개발을 실행할 때 승인된 자바스크립트 원본 필드에 http://localhosthttp://localhost:<port_number>를 모두 추가해야 합니다.

구현 확인

您可以通过使用验证实现的OAuth 2.0游乐场工具。

在工具中,执行以下步骤:

  1. 单击配置打开的OAuth 2.0配置窗口。
  2. OAuth流场中,选择客户端
  3. OAuth端点字段中,选择自定义
  4. 在相应字段中指定您的 OAuth 2.0 端点和您分配给 Google 的客户端 ID。
  5. 步骤1部分,不要选择任何谷歌范围。相反,将此字段留空或键入对您的服务器有效的范围(如果不使用 OAuth 范围,则输入任意字符串)。当您完成后,单击授权的API。
  6. 步骤2步骤3段,完成OAuth 2.0流程和验证每个步骤按预期工作。

您可以通过验证您的实现谷歌帐户链接演示工具。

在工具中,执行以下步骤:

  1. 点击登录在与谷歌按钮。
  2. 选择您要关联的帐户。
  3. 输入服务标识。
  4. (可选)输入您将请求访问的一个或多个范围。
  5. 单击开始演示
  6. 出现提示时,确认您可以同意并拒绝链接请求。
  7. 确认您被重定向到您的平台。