InfoGrab Docs

OAuth 2.0 ID 공급자 API

요약

이 API를 사용하여 OAuth 2.0 프로토콜로 서드파티 서비스가 사용자의 GitLab 리소스에 접근할 수 있도록 허용합니다. 이 기능은 doorkeeper Ruby gem을 기반으로 합니다. 많은 /oauth 엔드포인트가 교차 출처 리소스 공유(CORS)를 지원합니다.

이 API를 사용하여 OAuth 2.0 프로토콜로 서드파티 서비스가 사용자의 GitLab 리소스에 접근할 수 있도록 허용합니다. 자세한 내용은 GitLab을 OAuth 2.0 인증 ID 공급자로 구성을 참조하세요.

이 기능은 doorkeeper Ruby gem을 기반으로 합니다.

교차 출처 리소스 공유#

히스토리
  • CORS 사전 요청 지원이 GitLab 15.1에서 도입되었습니다.

많은 /oauth 엔드포인트가 교차 출처 리소스 공유(CORS)를 지원합니다. GitLab 15.1부터 다음 엔드포인트도 CORS 사전 요청을 지원합니다:

  • /oauth/revoke
  • /oauth/token
  • /oauth/userinfo

사전 요청에는 특정 헤더만 사용할 수 있습니다:

예를 들어, X-Requested-With 헤더는 사전 요청에 사용할 수 없습니다.

지원되는 OAuth 2.0 플로우#

GitLab은 다음 인증 플로우를 지원합니다:

  • PKCE(Proof Key for Code Exchange)를 사용한 인증 코드: 가장 안전합니다. PKCE 없이는 모바일 클라이언트에 클라이언트 비밀을 포함해야 하므로, 클라이언트 및 서버 앱 모두에 권장됩니다.
  • 인증 코드: 안전하고 일반적인 플로우. 안전한 서버 측 앱에 권장됩니다.
  • 기기 인증 부여 (GitLab 17.1 이상) 브라우저 접근이 없는 기기를 위한 안전한 플로우. 인증 플로우를 완료하려면 보조 기기가 필요합니다.

OAuth 2.1 초안 사양은 암묵적 부여와 리소스 소유자 비밀번호 자격증명 플로우를 모두 제외합니다.

플로우의 작동 방식과 사용 사례에 맞는 플로우를 선택하려면 OAuth RFC를 참조하세요.

PKCE 유무에 관계없이 인증 코드 플로우를 사용하려면 먼저 사용자 계정의 /user_settings/applications 페이지를 통해 application을 등록해야 합니다. 등록 시 적절한 범위를 활성화하여 application이 접근할 수 있는 리소스 범위를 제한할 수 있습니다. 생성 후 application 자격증명(_애플리케이션 ID_와 클라이언트 비밀)을 얻습니다. _클라이언트 비밀_은 반드시 안전하게 보관해야 합니다. 애플리케이션 아키텍처가 허용하는 경우 _애플리케이션 ID_도 비밀로 유지하는 것이 유리합니다.

GitLab의 범위 목록은 공급자 설명서를 참조하세요.

CSRF 공격 방지#

리디렉션 기반 플로우를 보호하기 위해 OAuth 사양은 /oauth/authorize 엔드포인트에 대한 각 요청에서 "사용자 에이전트에 안전하게 바인딩된 state 매개변수에 포함된 일회용 CSRF 토큰" 사용을 권장합니다. 이를 통해 CSRF 공격을 방지할 수 있습니다.

프로덕션에서 HTTPS 사용#

프로덕션 환경에서는 redirect_uri에 HTTPS를 사용하세요. 개발 환경에서는 GitLab이 안전하지 않은 HTTP 리디렉션 URI를 허용합니다.

OAuth 2.0은 보안을 전적으로 전송 계층에 의존하므로 보호되지 않은 URI를 사용하지 않아야 합니다. 자세한 내용은 OAuth 2.0 RFCOAuth 2.0 위협 모델 RFC를 참조하세요.

다음 섹션에서 각 플로우로 인증을 얻는 방법에 대한 자세한 지침을 찾을 수 있습니다.

PKCE(Proof Key for Code Exchange)를 사용한 인증 코드#

히스토리

PKCE RFC에는 인증 요청부터 액세스 토큰까지의 자세한 플로우 설명이 포함되어 있습니다. 다음 단계에서 플로우 구현을 설명합니다.

PKCE를 사용한 인증 코드 플로우(줄여서 PKCE)는 _클라이언트 비밀_에 전혀 접근하지 않고도 공개 클라이언트에서 클라이언트 자격증명과 액세스 토큰의 OAuth 교환을 안전하게 수행할 수 있습니다. 이로 인해 PKCE 플로우는 단일 페이지 JavaScript 애플리케이션이나 사용자로부터 비밀을 기술적으로 숨길 수 없는 다른 클라이언트 측 앱에 유리합니다.

플로우를 시작하기 전에 STATE, CODE_VERIFIERCODE_CHALLENGE를 생성하세요.

  • STATE는 클라이언트가 요청과 콜백 사이에 상태를 유지하는 데 사용하는 예측할 수 없는 값입니다. CSRF 토큰으로도 사용해야 합니다.
  • CODE_VERIFIER는 43~128자 길이의 임의 문자열로, A-Z, a-z, 0-9, -, ., _, ~ 문자를 사용합니다.
  • CODE_CHALLENGECODE_VERIFIER의 SHA256 해시를 URL-safe base64로 인코딩한 문자열입니다:
    • 인코딩 전 SHA256 해시는 바이너리 형식이어야 합니다.
    • Ruby에서는 Base64.urlsafe_encode64(Digest::SHA256.digest(CODE_VERIFIER), padding: false)로 설정할 수 있습니다.
    • 참고로, ks02i3jdikdo2k0dkfodf3m39rjfjsdk0wk349rj3jrhf CODE_VERIFIER 문자열을 이전 Ruby 스니펫으로 해시하고 인코딩하면 2i0WFA-0AerkjQm4X4oDEhqA17QIAKNjXpagHBXmO_U CODE_CHALLENGE 문자열이 생성됩니다.
  1. 인증 코드를 요청합니다. 다음 쿼리 매개변수를 사용하여 사용자를 /oauth/authorize 페이지로 리디렉션해야 합니다:

    https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES&code_challenge=CODE_CHALLENGE&code_challenge_method=S256&root_namespace_id=ROOT_NAMESPACE_ID
    

    이 페이지는 사용자에게 REQUESTED_SCOPES에 지정된 범위에 따라 앱이 계정에 접근하는 요청을 승인하도록 요청합니다. 그런 다음 사용자는 지정된 REDIRECT_URI로 리디렉션됩니다. 범위 매개변수는 사용자와 연결된 범위의 공백으로 구분된 목록입니다. 예를 들어, scope=read_user+profileread_userprofile 범위를 요청합니다. root_namespace_id는 프로젝트와 연결된 루트 네임스페이스 ID입니다. 이 선택적 매개변수는 연결된 그룹에 SAML SSO가 구성된 경우 사용해야 합니다. 리디렉션에는 인증 code가 포함됩니다. 예시:

    https://example.com/oauth/redirect?code=1234567890&state=STATE
    
  2. 이전 요청에서 반환된 인증 code(다음 예시에서 RETURNED_CODE로 표시)를 사용하여 HTTP 클라이언트로 access_token을 요청할 수 있습니다. 다음 예시는 Ruby의 rest-client를 사용합니다:

    parameters = 'client_id=APP_ID&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER'
    RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
     "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
     "token_type": "bearer",
     "expires_in": 7200,
     "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1",
     "created_at": 1607635748
    }
    
  3. access_token을 검색하려면 refresh_token 매개변수를 사용하세요. 리프레시 토큰은 access_token 자체가 만료된 후에도 사용할 수 있습니다. 이 요청은:

    • 기존 access_tokenrefresh_token을 무효화합니다.
    • 응답에서 새 토큰을 보냅니다.
      parameters = 'client_id=APP_ID&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI'
      RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
      "access_token": "c97d1fe52119f38c7f67f0a14db68d60caa35ddc86fd12401718b649dcfa9c68",
      "token_type": "bearer",
      "expires_in": 7200,
      "refresh_token": "803c1fd487fec35562c205dac93e9d8e08f9d3652a24079d704df3039df1158f",
      "created_at": 1628711391
    }
    
Note

redirect_uri는 원래 인증 요청에서 사용한 redirect_uri와 일치해야 합니다.

이제 액세스 토큰으로 API에 요청할 수 있습니다.

인증 코드 플로우#

히스토리
Note

자세한 플로우 설명은 RFC 사양을 확인하세요.

인증 코드 플로우는 본질적으로 PKCE를 사용한 인증 코드 플로우와 동일합니다.

플로우를 시작하기 전에 STATE를 생성하세요. 이는 클라이언트가 요청과 콜백 사이에 상태를 유지하는 데 사용하는 예측할 수 없는 값입니다. CSRF 토큰으로도 사용해야 합니다.

  1. 인증 코드를 요청합니다. 다음 쿼리 매개변수를 사용하여 사용자를 /oauth/authorize 페이지로 리디렉션해야 합니다:

    https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES&root_namespace_id=ROOT_NAMESPACE_ID
    

    이 페이지는 사용자에게 REQUESTED_SCOPES에 지정된 범위에 따라 앱이 계정에 접근하는 요청을 승인하도록 요청합니다. 그런 다음 사용자는 지정된 REDIRECT_URI로 리디렉션됩니다. 범위 매개변수는 사용자와 연결된 범위의 공백으로 구분된 목록입니다. 예를 들어, scope=read_user+profileread_userprofile 범위를 요청합니다. root_namespace_id는 프로젝트와 연결된 루트 네임스페이스 ID입니다. 이 선택적 매개변수는 연결된 그룹에 SAML SSO가 구성된 경우 사용해야 합니다. 리디렉션에는 인증 code가 포함됩니다. 예시:

    https://example.com/oauth/redirect?code=1234567890&state=STATE
    
  2. 이전 요청에서 반환된 인증 code(다음 예시에서 RETURNED_CODE로 표시)를 사용하여 HTTP 클라이언트로 access_token을 요청할 수 있습니다. 다음 예시는 Ruby의 rest-client를 사용합니다:

    parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
    RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
     "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
     "token_type": "bearer",
     "expires_in": 7200,
     "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1",
     "created_at": 1607635748
    }
    
  3. access_token을 검색하려면 refresh_token 매개변수를 사용하세요. 리프레시 토큰은 access_token 자체가 만료된 후에도 사용할 수 있습니다. 이 요청은:

    • 기존 access_tokenrefresh_token을 무효화합니다.
    • 응답에서 새 토큰을 보냅니다.
      parameters = 'client_id=APP_ID&client_secret=APP_SECRET&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI'
      RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
      "access_token": "c97d1fe52119f38c7f67f0a14db68d60caa35ddc86fd12401718b649dcfa9c68",
      "token_type": "bearer",
      "expires_in": 7200,
      "refresh_token": "803c1fd487fec35562c205dac93e9d8e08f9d3652a24079d704df3039df1158f",
      "created_at": 1628711391
    }
    
Note

redirect_uri는 원래 인증 요청에서 사용한 redirect_uri와 일치해야 합니다.

이제 반환된 액세스 토큰으로 API에 요청할 수 있습니다.

기기 인증 부여 플로우#

히스토리
Note

브라우저 로그인에서 기기 인증 요청부터 토큰 응답까지 기기 인증 부여 플로우에 대한 자세한 설명은 RFC 사양을 확인하세요.

기기 인증 부여 플로우는 브라우저 상호작용이 불가능한 입력 제한 기기에서 GitLab ID를 안전하게 인증할 수 있습니다.

이로 인해 기기 인증 부여 플로우는 UI가 없거나 제한된 헤드리스 서버 또는 다른 기기에서 GitLab 서비스를 사용하려는 사용자에게 이상적입니다.

  1. 기기 인증을 요청하려면 입력 제한 기기 클라이언트에서 https://gitlab.example.com/oauth/authorize_device로 요청을 보냅니다. 예시:

      parameters = 'client_id=UID&scope=read'
      RestClient.post 'https://gitlab.example.com/oauth/authorize_device', parameters
    

    요청이 성공하면 verification_uri가 포함된 응답이 사용자에게 반환됩니다. 예시:

    {
        "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
        "user_code": "0A44L90H",
        "verification_uri": "https://gitlab.example.com/oauth/device",
        "verification_uri_complete": "https://gitlab.example.com/oauth/device?user_code=0A44L90H",
        "expires_in": 300,
        "interval": 5
    }
    
  2. 기기 클라이언트는 응답에서 user_codeverification_uri를 요청한 사용자에게 표시합니다. 그런 다음 사용자는 브라우저 접근이 있는 보조 기기에서:

    1. 제공된 URI로 이동합니다.
    2. 사용자 코드를 입력합니다.
    3. 요청에 따라 인증을 완료합니다.
  3. verification_uriuser_code를 표시한 직후, 기기 클라이언트는 초기 응답에서 반환된 관련 device_code로 토큰 엔드포인트를 폴링하기 시작합니다:

    parameters = 'grant_type=urn:ietf:params:oauth:grant-type:device_code
    &device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
    &client_id=1406020730'
    RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    
  4. 기기 클라이언트는 토큰 엔드포인트에서 응답을 받습니다. 인증이 성공하면 성공 응답이 반환되고, 그렇지 않으면 오류 응답이 반환됩니다. 잠재적 오류 응답은 다음 중 하나로 분류됩니다:

    • OAuth 인증 프레임워크 액세스 토큰 오류 응답에 의해 정의된 것.
    • 여기에 설명된 기기 인증 부여 플로우에 특정한 것.

    기기 플로우에 특정한 오류 응답은 다음 내용에 설명되어 있습니다. 각 잠재적 응답에 대한 자세한 내용은 기기 인증 부여에 대한 관련 RFC 사양인증 토큰에 대한 RFC 사양을 참조하세요.

    응답 예시:

    {
      "error": "authorization_pending",
      "error_description": "..."
    }
    

    이 응답을 받으면 기기 클라이언트는 계속 폴링합니다.

    폴링 간격이 너무 짧으면 속도 저하 오류 응답이 반환됩니다. 예시:

    {
      "error": "slow_down",
      "error_description": "..."
    }
    

    이 응답을 받으면 기기 클라이언트는 폴링 속도를 줄이고 새 속도로 계속 폴링합니다.

    인증이 완료되기 전에 기기 코드가 만료되면 토큰 만료 오류 응답이 반환됩니다. 예시:

    {
      "error": "expired_token",
      "error_description": "..."
    }
    

    이 시점에서 기기 클라이언트는 중지하고 새 기기 인증 요청을 시작해야 합니다.

    인증 요청이 거부되면 접근 거부 오류 응답이 반환됩니다. 예시:

    {
      "error": "access_denied",
      "error_description": "..."
    }
    

    인증 요청이 거부되었습니다. 사용자는 자격증명을 확인하거나 시스템 관리자에게 문의해야 합니다.

  5. 사용자가 성공적으로 인증하면 성공 응답이 반환됩니다:

    {
        "access_token": "TOKEN",
        "token_type": "Bearer",
        "expires_in": 7200,
        "scope": "read",
        "created_at": 1593096829
    }
    

이 시점에서 기기 인증 플로우가 완료됩니다. 반환된 access_token은 HTTPS를 통한 복제나 API 접근 등 GitLab 리소스에 접근할 때 사용자 ID를 인증하기 위해 GitLab에 제공할 수 있습니다.

클라이언트 측 기기 플로우를 구현하는 샘플 애플리케이션은 https://gitlab.com/johnwparent/git-auth-over-https에서 찾을 수 있습니다.

access token으로 GitLab API 접근#

access token을 사용하면 사용자를 대신하여 API에 요청할 수 있습니다. 토큰을 GET 매개변수로 전달할 수 있습니다:

GET https://gitlab.example.com/api/v4/user?access_token=OAUTH-TOKEN

또는 Authorization 헤더에 토큰을 넣을 수 있습니다:

curl --header "Authorization: Bearer OAUTH-TOKEN" "https://gitlab.example.com/api/v4/user"

access token으로 HTTPS를 통한 Git 접근#

범위 read_repository 또는 write_repository가 있는 토큰은 HTTPS를 통해 Git에 접근할 수 있습니다. 토큰을 비밀번호로 사용하세요. 사용자 이름은 임의의 문자열 값으로 설정할 수 있습니다. oauth2를 사용하는 것이 좋습니다:

https://oauth2:<your_access_token>@gitlab.example.com/project_path/project_name.git

또는 Git 자격증명 도우미를 사용하여 OAuth로 GitLab에 인증할 수 있습니다. 이는 OAuth 토큰 갱신을 자동으로 처리합니다.

토큰 정보 검색#

토큰의 세부 정보를 확인하려면 Doorkeeper gem이 제공하는 token/info 엔드포인트를 사용하세요. 자세한 내용은 /oauth/token/info를 참조하세요.

액세스 토큰을 제공해야 합니다:

  • 매개변수로:

    GET https://gitlab.example.com/oauth/token/info?access_token=
    
  • Authorization 헤더로:

    curl --header "Authorization: Bearer " "https://gitlab.example.com/oauth/token/info"
    

응답 예시:

{
    "resource_owner_id": 1,
    "scope": ["api"],
    "expires_in": null,
    "application": {"uid": "1cb242f495280beb4291e64bee2a17f330902e499882fe8e1e2aa875519cab33"},
    "created_at": 1575890427
}

더 이상 사용되지 않는 필드#

scopesexpires_in_seconds 필드가 응답에 포함되지만 현재 더 이상 사용되지 않습니다. scopes 필드는 scope의 별칭이고, expires_in_seconds 필드는 expires_in의 별칭입니다. 자세한 내용은 Doorkeeper API 변경 사항을 참조하세요.

토큰 취소#

토큰을 취소하려면 revoke 엔드포인트를 사용하세요. API는 성공을 나타내기 위해 200 응답 코드와 빈 JSON 해시를 반환합니다.

parameters = 'client_id=APP_ID&client_secret=APP_SECRET&token=TOKEN'
RestClient.post 'https://gitlab.example.com/oauth/revoke', parameters

OAuth 2.0 토큰과 GitLab 레지스트리#

표준 OAuth 2.0 토큰은 다음과 같이 GitLab 레지스트리에 대한 다양한 수준의 접근을 지원합니다:

OAuth 2.0 ID 공급자 API

Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기
요약

이 API를 사용하여 OAuth 2.0 프로토콜로 서드파티 서비스가 사용자의 GitLab 리소스에 접근할 수 있도록 허용합니다. 이 기능은 doorkeeper Ruby gem을 기반으로 합니다. 많은 /oauth 엔드포인트가 교차 출처 리소스 공유(CORS)를 지원합니다.

이 API를 사용하여 OAuth 2.0 프로토콜로 서드파티 서비스가 사용자의 GitLab 리소스에 접근할 수 있도록 허용합니다. 자세한 내용은 GitLab을 OAuth 2.0 인증 ID 공급자로 구성을 참조하세요.

이 기능은 doorkeeper Ruby gem을 기반으로 합니다.

교차 출처 리소스 공유#

히스토리
  • CORS 사전 요청 지원이 GitLab 15.1에서 도입되었습니다.

많은 /oauth 엔드포인트가 교차 출처 리소스 공유(CORS)를 지원합니다. GitLab 15.1부터 다음 엔드포인트도 CORS 사전 요청을 지원합니다:

  • /oauth/revoke
  • /oauth/token
  • /oauth/userinfo

사전 요청에는 특정 헤더만 사용할 수 있습니다:

예를 들어, X-Requested-With 헤더는 사전 요청에 사용할 수 없습니다.

지원되는 OAuth 2.0 플로우#

GitLab은 다음 인증 플로우를 지원합니다:

  • PKCE(Proof Key for Code Exchange)를 사용한 인증 코드: 가장 안전합니다. PKCE 없이는 모바일 클라이언트에 클라이언트 비밀을 포함해야 하므로, 클라이언트 및 서버 앱 모두에 권장됩니다.
  • 인증 코드: 안전하고 일반적인 플로우. 안전한 서버 측 앱에 권장됩니다.
  • 기기 인증 부여 (GitLab 17.1 이상) 브라우저 접근이 없는 기기를 위한 안전한 플로우. 인증 플로우를 완료하려면 보조 기기가 필요합니다.

OAuth 2.1 초안 사양은 암묵적 부여와 리소스 소유자 비밀번호 자격증명 플로우를 모두 제외합니다.

플로우의 작동 방식과 사용 사례에 맞는 플로우를 선택하려면 OAuth RFC를 참조하세요.

PKCE 유무에 관계없이 인증 코드 플로우를 사용하려면 먼저 사용자 계정의 /user_settings/applications 페이지를 통해 application을 등록해야 합니다. 등록 시 적절한 범위를 활성화하여 application이 접근할 수 있는 리소스 범위를 제한할 수 있습니다. 생성 후 application 자격증명(_애플리케이션 ID_와 클라이언트 비밀)을 얻습니다. _클라이언트 비밀_은 반드시 안전하게 보관해야 합니다. 애플리케이션 아키텍처가 허용하는 경우 _애플리케이션 ID_도 비밀로 유지하는 것이 유리합니다.

GitLab의 범위 목록은 공급자 설명서를 참조하세요.

CSRF 공격 방지#

리디렉션 기반 플로우를 보호하기 위해 OAuth 사양은 /oauth/authorize 엔드포인트에 대한 각 요청에서 "사용자 에이전트에 안전하게 바인딩된 state 매개변수에 포함된 일회용 CSRF 토큰" 사용을 권장합니다. 이를 통해 CSRF 공격을 방지할 수 있습니다.

프로덕션에서 HTTPS 사용#

프로덕션 환경에서는 redirect_uri에 HTTPS를 사용하세요. 개발 환경에서는 GitLab이 안전하지 않은 HTTP 리디렉션 URI를 허용합니다.

OAuth 2.0은 보안을 전적으로 전송 계층에 의존하므로 보호되지 않은 URI를 사용하지 않아야 합니다. 자세한 내용은 OAuth 2.0 RFCOAuth 2.0 위협 모델 RFC를 참조하세요.

다음 섹션에서 각 플로우로 인증을 얻는 방법에 대한 자세한 지침을 찾을 수 있습니다.

PKCE(Proof Key for Code Exchange)를 사용한 인증 코드#

히스토리

PKCE RFC에는 인증 요청부터 액세스 토큰까지의 자세한 플로우 설명이 포함되어 있습니다. 다음 단계에서 플로우 구현을 설명합니다.

PKCE를 사용한 인증 코드 플로우(줄여서 PKCE)는 _클라이언트 비밀_에 전혀 접근하지 않고도 공개 클라이언트에서 클라이언트 자격증명과 액세스 토큰의 OAuth 교환을 안전하게 수행할 수 있습니다. 이로 인해 PKCE 플로우는 단일 페이지 JavaScript 애플리케이션이나 사용자로부터 비밀을 기술적으로 숨길 수 없는 다른 클라이언트 측 앱에 유리합니다.

플로우를 시작하기 전에 STATE, CODE_VERIFIERCODE_CHALLENGE를 생성하세요.

  • STATE는 클라이언트가 요청과 콜백 사이에 상태를 유지하는 데 사용하는 예측할 수 없는 값입니다. CSRF 토큰으로도 사용해야 합니다.
  • CODE_VERIFIER는 43~128자 길이의 임의 문자열로, A-Z, a-z, 0-9, -, ., _, ~ 문자를 사용합니다.
  • CODE_CHALLENGECODE_VERIFIER의 SHA256 해시를 URL-safe base64로 인코딩한 문자열입니다:
    • 인코딩 전 SHA256 해시는 바이너리 형식이어야 합니다.
    • Ruby에서는 Base64.urlsafe_encode64(Digest::SHA256.digest(CODE_VERIFIER), padding: false)로 설정할 수 있습니다.
    • 참고로, ks02i3jdikdo2k0dkfodf3m39rjfjsdk0wk349rj3jrhf CODE_VERIFIER 문자열을 이전 Ruby 스니펫으로 해시하고 인코딩하면 2i0WFA-0AerkjQm4X4oDEhqA17QIAKNjXpagHBXmO_U CODE_CHALLENGE 문자열이 생성됩니다.
  1. 인증 코드를 요청합니다. 다음 쿼리 매개변수를 사용하여 사용자를 /oauth/authorize 페이지로 리디렉션해야 합니다:

    https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES&code_challenge=CODE_CHALLENGE&code_challenge_method=S256&root_namespace_id=ROOT_NAMESPACE_ID
    

    이 페이지는 사용자에게 REQUESTED_SCOPES에 지정된 범위에 따라 앱이 계정에 접근하는 요청을 승인하도록 요청합니다. 그런 다음 사용자는 지정된 REDIRECT_URI로 리디렉션됩니다. 범위 매개변수는 사용자와 연결된 범위의 공백으로 구분된 목록입니다. 예를 들어, scope=read_user+profileread_userprofile 범위를 요청합니다. root_namespace_id는 프로젝트와 연결된 루트 네임스페이스 ID입니다. 이 선택적 매개변수는 연결된 그룹에 SAML SSO가 구성된 경우 사용해야 합니다. 리디렉션에는 인증 code가 포함됩니다. 예시:

    https://example.com/oauth/redirect?code=1234567890&state=STATE
    
  2. 이전 요청에서 반환된 인증 code(다음 예시에서 RETURNED_CODE로 표시)를 사용하여 HTTP 클라이언트로 access_token을 요청할 수 있습니다. 다음 예시는 Ruby의 rest-client를 사용합니다:

    parameters = 'client_id=APP_ID&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER'
    RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
     "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
     "token_type": "bearer",
     "expires_in": 7200,
     "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1",
     "created_at": 1607635748
    }
    
  3. access_token을 검색하려면 refresh_token 매개변수를 사용하세요. 리프레시 토큰은 access_token 자체가 만료된 후에도 사용할 수 있습니다. 이 요청은:

    • 기존 access_tokenrefresh_token을 무효화합니다.
    • 응답에서 새 토큰을 보냅니다.
      parameters = 'client_id=APP_ID&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI'
      RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
      "access_token": "c97d1fe52119f38c7f67f0a14db68d60caa35ddc86fd12401718b649dcfa9c68",
      "token_type": "bearer",
      "expires_in": 7200,
      "refresh_token": "803c1fd487fec35562c205dac93e9d8e08f9d3652a24079d704df3039df1158f",
      "created_at": 1628711391
    }
    
Note

redirect_uri는 원래 인증 요청에서 사용한 redirect_uri와 일치해야 합니다.

이제 액세스 토큰으로 API에 요청할 수 있습니다.

인증 코드 플로우#

히스토리
Note

자세한 플로우 설명은 RFC 사양을 확인하세요.

인증 코드 플로우는 본질적으로 PKCE를 사용한 인증 코드 플로우와 동일합니다.

플로우를 시작하기 전에 STATE를 생성하세요. 이는 클라이언트가 요청과 콜백 사이에 상태를 유지하는 데 사용하는 예측할 수 없는 값입니다. CSRF 토큰으로도 사용해야 합니다.

  1. 인증 코드를 요청합니다. 다음 쿼리 매개변수를 사용하여 사용자를 /oauth/authorize 페이지로 리디렉션해야 합니다:

    https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES&root_namespace_id=ROOT_NAMESPACE_ID
    

    이 페이지는 사용자에게 REQUESTED_SCOPES에 지정된 범위에 따라 앱이 계정에 접근하는 요청을 승인하도록 요청합니다. 그런 다음 사용자는 지정된 REDIRECT_URI로 리디렉션됩니다. 범위 매개변수는 사용자와 연결된 범위의 공백으로 구분된 목록입니다. 예를 들어, scope=read_user+profileread_userprofile 범위를 요청합니다. root_namespace_id는 프로젝트와 연결된 루트 네임스페이스 ID입니다. 이 선택적 매개변수는 연결된 그룹에 SAML SSO가 구성된 경우 사용해야 합니다. 리디렉션에는 인증 code가 포함됩니다. 예시:

    https://example.com/oauth/redirect?code=1234567890&state=STATE
    
  2. 이전 요청에서 반환된 인증 code(다음 예시에서 RETURNED_CODE로 표시)를 사용하여 HTTP 클라이언트로 access_token을 요청할 수 있습니다. 다음 예시는 Ruby의 rest-client를 사용합니다:

    parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
    RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
     "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
     "token_type": "bearer",
     "expires_in": 7200,
     "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1",
     "created_at": 1607635748
    }
    
  3. access_token을 검색하려면 refresh_token 매개변수를 사용하세요. 리프레시 토큰은 access_token 자체가 만료된 후에도 사용할 수 있습니다. 이 요청은:

    • 기존 access_tokenrefresh_token을 무효화합니다.
    • 응답에서 새 토큰을 보냅니다.
      parameters = 'client_id=APP_ID&client_secret=APP_SECRET&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI'
      RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    

    응답 예시:

    {
      "access_token": "c97d1fe52119f38c7f67f0a14db68d60caa35ddc86fd12401718b649dcfa9c68",
      "token_type": "bearer",
      "expires_in": 7200,
      "refresh_token": "803c1fd487fec35562c205dac93e9d8e08f9d3652a24079d704df3039df1158f",
      "created_at": 1628711391
    }
    
Note

redirect_uri는 원래 인증 요청에서 사용한 redirect_uri와 일치해야 합니다.

이제 반환된 액세스 토큰으로 API에 요청할 수 있습니다.

기기 인증 부여 플로우#

히스토리
Note

브라우저 로그인에서 기기 인증 요청부터 토큰 응답까지 기기 인증 부여 플로우에 대한 자세한 설명은 RFC 사양을 확인하세요.

기기 인증 부여 플로우는 브라우저 상호작용이 불가능한 입력 제한 기기에서 GitLab ID를 안전하게 인증할 수 있습니다.

이로 인해 기기 인증 부여 플로우는 UI가 없거나 제한된 헤드리스 서버 또는 다른 기기에서 GitLab 서비스를 사용하려는 사용자에게 이상적입니다.

  1. 기기 인증을 요청하려면 입력 제한 기기 클라이언트에서 https://gitlab.example.com/oauth/authorize_device로 요청을 보냅니다. 예시:

      parameters = 'client_id=UID&scope=read'
      RestClient.post 'https://gitlab.example.com/oauth/authorize_device', parameters
    

    요청이 성공하면 verification_uri가 포함된 응답이 사용자에게 반환됩니다. 예시:

    {
        "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
        "user_code": "0A44L90H",
        "verification_uri": "https://gitlab.example.com/oauth/device",
        "verification_uri_complete": "https://gitlab.example.com/oauth/device?user_code=0A44L90H",
        "expires_in": 300,
        "interval": 5
    }
    
  2. 기기 클라이언트는 응답에서 user_codeverification_uri를 요청한 사용자에게 표시합니다. 그런 다음 사용자는 브라우저 접근이 있는 보조 기기에서:

    1. 제공된 URI로 이동합니다.
    2. 사용자 코드를 입력합니다.
    3. 요청에 따라 인증을 완료합니다.
  3. verification_uriuser_code를 표시한 직후, 기기 클라이언트는 초기 응답에서 반환된 관련 device_code로 토큰 엔드포인트를 폴링하기 시작합니다:

    parameters = 'grant_type=urn:ietf:params:oauth:grant-type:device_code
    &device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
    &client_id=1406020730'
    RestClient.post 'https://gitlab.example.com/oauth/token', parameters
    
  4. 기기 클라이언트는 토큰 엔드포인트에서 응답을 받습니다. 인증이 성공하면 성공 응답이 반환되고, 그렇지 않으면 오류 응답이 반환됩니다. 잠재적 오류 응답은 다음 중 하나로 분류됩니다:

    • OAuth 인증 프레임워크 액세스 토큰 오류 응답에 의해 정의된 것.
    • 여기에 설명된 기기 인증 부여 플로우에 특정한 것.

    기기 플로우에 특정한 오류 응답은 다음 내용에 설명되어 있습니다. 각 잠재적 응답에 대한 자세한 내용은 기기 인증 부여에 대한 관련 RFC 사양인증 토큰에 대한 RFC 사양을 참조하세요.

    응답 예시:

    {
      "error": "authorization_pending",
      "error_description": "..."
    }
    

    이 응답을 받으면 기기 클라이언트는 계속 폴링합니다.

    폴링 간격이 너무 짧으면 속도 저하 오류 응답이 반환됩니다. 예시:

    {
      "error": "slow_down",
      "error_description": "..."
    }
    

    이 응답을 받으면 기기 클라이언트는 폴링 속도를 줄이고 새 속도로 계속 폴링합니다.

    인증이 완료되기 전에 기기 코드가 만료되면 토큰 만료 오류 응답이 반환됩니다. 예시:

    {
      "error": "expired_token",
      "error_description": "..."
    }
    

    이 시점에서 기기 클라이언트는 중지하고 새 기기 인증 요청을 시작해야 합니다.

    인증 요청이 거부되면 접근 거부 오류 응답이 반환됩니다. 예시:

    {
      "error": "access_denied",
      "error_description": "..."
    }
    

    인증 요청이 거부되었습니다. 사용자는 자격증명을 확인하거나 시스템 관리자에게 문의해야 합니다.

  5. 사용자가 성공적으로 인증하면 성공 응답이 반환됩니다:

    {
        "access_token": "TOKEN",
        "token_type": "Bearer",
        "expires_in": 7200,
        "scope": "read",
        "created_at": 1593096829
    }
    

이 시점에서 기기 인증 플로우가 완료됩니다. 반환된 access_token은 HTTPS를 통한 복제나 API 접근 등 GitLab 리소스에 접근할 때 사용자 ID를 인증하기 위해 GitLab에 제공할 수 있습니다.

클라이언트 측 기기 플로우를 구현하는 샘플 애플리케이션은 https://gitlab.com/johnwparent/git-auth-over-https에서 찾을 수 있습니다.

access token으로 GitLab API 접근#

access token을 사용하면 사용자를 대신하여 API에 요청할 수 있습니다. 토큰을 GET 매개변수로 전달할 수 있습니다:

GET https://gitlab.example.com/api/v4/user?access_token=OAUTH-TOKEN

또는 Authorization 헤더에 토큰을 넣을 수 있습니다:

curl --header "Authorization: Bearer OAUTH-TOKEN" "https://gitlab.example.com/api/v4/user"

access token으로 HTTPS를 통한 Git 접근#

범위 read_repository 또는 write_repository가 있는 토큰은 HTTPS를 통해 Git에 접근할 수 있습니다. 토큰을 비밀번호로 사용하세요. 사용자 이름은 임의의 문자열 값으로 설정할 수 있습니다. oauth2를 사용하는 것이 좋습니다:

https://oauth2:<your_access_token>@gitlab.example.com/project_path/project_name.git

또는 Git 자격증명 도우미를 사용하여 OAuth로 GitLab에 인증할 수 있습니다. 이는 OAuth 토큰 갱신을 자동으로 처리합니다.

토큰 정보 검색#

토큰의 세부 정보를 확인하려면 Doorkeeper gem이 제공하는 token/info 엔드포인트를 사용하세요. 자세한 내용은 /oauth/token/info를 참조하세요.

액세스 토큰을 제공해야 합니다:

  • 매개변수로:

    GET https://gitlab.example.com/oauth/token/info?access_token=
    
  • Authorization 헤더로:

    curl --header "Authorization: Bearer " "https://gitlab.example.com/oauth/token/info"
    

응답 예시:

{
    "resource_owner_id": 1,
    "scope": ["api"],
    "expires_in": null,
    "application": {"uid": "1cb242f495280beb4291e64bee2a17f330902e499882fe8e1e2aa875519cab33"},
    "created_at": 1575890427
}

더 이상 사용되지 않는 필드#

scopesexpires_in_seconds 필드가 응답에 포함되지만 현재 더 이상 사용되지 않습니다. scopes 필드는 scope의 별칭이고, expires_in_seconds 필드는 expires_in의 별칭입니다. 자세한 내용은 Doorkeeper API 변경 사항을 참조하세요.

토큰 취소#

토큰을 취소하려면 revoke 엔드포인트를 사용하세요. API는 성공을 나타내기 위해 200 응답 코드와 빈 JSON 해시를 반환합니다.

parameters = 'client_id=APP_ID&client_secret=APP_SECRET&token=TOKEN'
RestClient.post 'https://gitlab.example.com/oauth/revoke', parameters

OAuth 2.0 토큰과 GitLab 레지스트리#

표준 OAuth 2.0 토큰은 다음과 같이 GitLab 레지스트리에 대한 다양한 수준의 접근을 지원합니다: