- 크로스 오리진 리소스 공유
- 지원되는 OAuth 2.0 플로우
access token
을 사용한 GitLab API 액세스access token
을 사용한 HTTPS로 Git 액세스- 토큰 정보 검색
- 토큰 취소
- OAuth 2.0 토큰 및 GitLab 레지스트리
OAuth 2.0 식별 공급자 API
GitLab은 OAuth 2.0 프로토콜을 통해 제3자 서비스가 사용자를 대신하여 GitLab 리소스에 액세스할 수 있도록 하는 API를 제공합니다.
이를 위해 GitLab을 구성하려면 OAuth 2.0 인증 식별 공급자로서의 GitLab 구성을 참조하십시오.
이 기능은 doorkeeper Ruby gem을 기반으로 합니다.
크로스 오리진 리소스 공유
- CORS 사전 요청 지원은 GitLab 15.1에서 소개되었습니다.
많은 /oauth
엔드포인트가 크로스 오리진 리소스 공유 (CORS)를 지원합니다. GitLab 15.1부터 다음 엔드포인트도 CORS 사전 요청을 지원합니다:
/oauth/revoke
/oauth/token
/oauth/userinfo
일부 헤더만 사전 요청에 사용할 수 있습니다:
- 간단한 요청에 나열된 헤더.
-
Authorization
헤더.
예를 들어 X-Requested-With
헤더는 사전 요청에 사용할 수 없습니다.
지원되는 OAuth 2.0 플로우
GitLab은 다음 인가 플로우를 지원합니다:
- Proof Key for Code Exchange (PKCE)로 인증 코드: 가장 안전합니다. PKCE 없이는 모바일 클라이언트에 클라이언트 비밀을 포함해야 하며, 클라이언트 및 서버 앱 양쪽에 모두 권장됩니다.
- 인가 코드: 안전하고 일반적인 플로우입니다. 안전한 서버 앱에 대한 권장 옵션입니다.
- 리소스 소유자 암호 자격 증명: 안전하게 호스팅된 제1자 서비스에 만 사용되어야 합니다. GitLab은 이 플로우의 사용을 권장하지 않습니다.
디바이스 인가 그랜트는 지원되지 않습니다. 이슈 332682에서 지원을 제안하고 있습니다.
OAuth 2.1의 초안 명세서는 명시적 그랜트와 리소스 소유자 암호 자격 증명 플로우를 모두 배제합니다.
모든 이러한 플로우가 작동하는 방식 및 귀하의 사용 사례에 적합한 올바른 플로우를 선택하는 데 도움이 되도록 OAuth RFC를 참조하십시오.
인가 코드(코드 포함 여부에 관계 없이) 플로우를 위해서는 먼저 /user_settings/applications
페이지에서 application
을 등록해야 합니다. 등록하는 동안 적절한 스코프를 활성화하여 application
이 액세스할 수 있는 리소스 범위를 제한할 수 있습니다. 생성 후에는 application
자격 증명인 Application ID 및 _Client Secret_를 획들할 수 있습니다. Client Secret는 안전하게 유지해야 합니다. 또한 귀하의 응용 프로그램 아키텍처가 허용하는 경우 _Application ID_도 비밀로 유지하는 것이 유리합니다.
GitLab의 스코프 목록은 공급자 문서를 참조하십시오.
CSRF 공격 방지
리디렉션 기반 플로우 보호를 위해 OAuth 명세서는 “사용자 에이전트에 안전하게 바인딩된 상태 매개변수에 포함된 일회용 CSRF 토큰”의 사용을 권장합니다. 이를 통해 /oauth/authorize
엔드포인트로의 각 요청마다 CSRF 공격을 방지할 수 있습니다.
프로덕션에서는 HTTPS 사용
프로덕션에서는 redirect_uri
에 대해 HTTPS를 사용해야 합니다. 개발 중에는 GitLab이 보안되지 않은 HTTP 리디렉트 URI를 허용합니다.
OAuth 2.0은 보안을 전적으로 전송 계층에 의존하기 때문에 보호되지 않은 URI를 사용해서는 안 됩니다. 자세한 내용은 OAuth 2.0 RFC 및 OAuth 2.0 위협 모델 RFC을 참조하십시오.
다음 섹션에서는 각 플로우로 권한 부여하는 방법에 대한 자세한 지침을 찾을 수 있습니다.
Proof Key for Code Exchange (PKCE)로 인증 코드
PKCE RFC에는 권한 부여 요청부터 액세스 토큰까지의 자세한 플로우 설명이 포함되어 있습니다. 다음 단계는 플로우의 구현을 설명합니다.
인증 코드와 PKCE 플로우, 약자인 PKCE는 _Client Secret_에 액세스하지 않고도 공개 클라이언트에서 클라이언트 자격 증명을 안전하게 OAuth 교환할 수 있도록 합니다. 이는 사용자에게 비밀을 유지할 수 없는 단일 페이지 JavaScript 응용 프로그램이나 기타 클라이언트 측 앱에 대해 PKCE 플로우가 유리합니다.
플로우를 시작하기 전에 STATE
, CODE_VERIFIER
, 및 CODE_CHALLENGE
를 생성하십시오.
-
STATE
는 클라이언트가 요청과 콜백 사이의 상태를 유지하는 데 사용하는 예측할 수 없는 값입니다. 또한 CSRF 토큰으로 사용해야 합니다. -
CODE_VERIFIER
는 길이가 43 ~ 128 자리인 임의의 문자열로,A-Z
,a-z
,0-9
,-
,.
,_
및~
문자를 사용합니다. -
CODE_CHALLENGE
는CODE_VERIFIER
의 SHA256 해시의 URL-세이프한 base64로 인코딩된 문자열입니다.- 인코딩하기 전에 SHA256 해시는 이진 형식이어야 합니다.
- Ruby에서는
Base64.urlsafe_encode64(Digest::SHA256.digest(CODE_VERIFIER), padding: false)
로 설정할 수 있습니다. - 예를 들어 Ruby 조각을 사용하여 해시된 및 인코딩된
CODE_VERIFIER
문자열인ks02i3jdikdo2k0dkfodf3m39rjfjsdk0wk349rj3jrhf
은 위의 Ruby 조각을 사용하여CODE_CHALLENGE
문자열인2i0WFA-0AerkjQm4X4oDEhqA17QIAKNjXpagHBXmO_U
을 생성합니다.
-
인가 코드를 요청하려면 다음 쿼리 매개변수를 사용하여 사용자를
/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
이 페이지에서 사용자에게
REQUESTED_SCOPES
에서 지정된 스코프에 따라 계정에 액세스하기 위한 앱의 요청을 승인할 것인지 묻습니다. 사용자는 지정된REDIRECT_URI
로 다시 리디렉션됩니다. scope 매개변수는 사용자와 관련된 스코프의 공백으로 구분된 목록입니다. 예를 들어scope=read_user+profile
은read_user
및profile
스코프를 요청합니다. 리디렉션에는 인가code
가 포함됩니다. 예:https://example.com/oauth/redirect?code=1234567890&state=STATE
-
이전 요청에서 반환된 인가
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 }
-
새로운
access_token
을 검색하려면refresh_token
매개변수를 사용하십시오.access_token
자체가 만료된 후에도refresh_token
을 사용할 수 있습니다. 이 요청은:- 기존
access_token
및refresh_token
을 무효화합니다. - 응답에서 새 토큰을 보냅니다.
parameters = 'client_id=APP_ID&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER' RestClient.post 'https://gitlab.example.com/oauth/token', parameters
예시 응답:
{ "access_token": "c97d1fe52119f38c7f67f0a14db68d60caa35ddc86fd12401718b649dcfa9c68", "token_type": "bearer", "expires_in": 7200, "refresh_token": "803c1fd487fec35562c205dac93e9d8e08f9d3652a24079d704df3039df1158f", "created_at": 1628711391 }
- 기존
참고:
redirect_uri
는 원본 인가 요청에서 사용한 redirect_uri
와 일치해야 합니다.
이제 액세스 토큰으로 API에 요청을 보낼 수 있습니다.
인가 코드 플로우
참고: 자세한 플로우 설명은 RFC 사언를 확인하세요.
인가 코드 플로우는 기본적으로 PKCE를 사용한 인가 코드 플로우와 동일합니다.
플로우를 시작하기 전에 STATE
를 생성합니다. 이 값은 클라이언트가 요청과 콜백 사이의 상태를 유지하기 위해 사용하는 예측할 수 없는 값입니다. 또한 CSRF 토큰으로 사용되어야 합니다.
-
인가 코드 요청. 이를 위해서는 다음 쿼리 매개변수를 사용하여 사용자를
/oauth/authorize
페이지로 리디렉션해야 합니다:https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES
이 페이지에서 사용자는
REQUESTED_SCOPES
에 지정된 스코프를 기반으로 앱에 대한 요청을 승인하도록 요청됩니다. 사용자는 지정된REDIRECT_URI
로 다시 리디렉션됩니다. 스코프 매개변수는 사용자와 관련된 스코프의 공백으로 구분된 목록입니다. 예를 들어scope=read_user+profile
는read_user
및profile
스코프를 요청합니다. 리디렉션에는 인가code
가 포함됩니다. 예:https://example.com/oauth/redirect?code=1234567890&state=STATE
-
이전 요청에서 반환된 인가
code
(다음 예제에서RETURNED_CODE
로 표시)를 사용하여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 }
-
새로운
access_token
을 검색하려면refresh_token
매개변수를 사용하십시오.access_token
이 만료된 후에도refresh_token
을 사용할 수 있습니다. 이 요청은 다음을 수행합니다:- 기존
access_token
및refresh_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 }
- 기존
참고:
redirect_uri
는 원래 인가 요청에 사용된 redirect_uri
와 일치해야 합니다.
이제 반환된 액세스 토큰을 사용하여 API에 요청을 보낼 수 있습니다.
리소스 소유자 비밀번호 자격 증명 플로우
참고: 자세한 플로우 설명은 RFC 사언를 확인하세요.
참고: 리소스 소유자 비밀번호 자격 증명은 이중 인증을 사용하는 사용자에게는 비활성화돼 있습니다. 이러한 사용자는 대신 개인 액세스 토큰을 사용하여 API에 액세스할 수 있습니다.
이 플로우에서는 리소스 소유자 자격 증명(사용자 이름 및 비밀번호)와 교환을 위해 토큰이 요청됩니다.
다음의 경우에만 자격 증명을 사용해야 합니다: - 리소스 소유자와 클라이언트 간에 높은 신뢰도가 있다면. 예를 들어, 클라이언트가 장치 운영 체제의 일부이거나 높은 권한을 가진 애플리케이션인 경우. - 다른 인가 부여 유형이 사용할 수 없는 경우(예: 인가 코드).
경고: 사용자 자격 증명을 저장해서는 안 되며, 클라이언트가 신뢰할 수 있는 환경에 배포된 경우에만 이 부여 유형을 사용해야 합니다. 99%의 경우에는 개인 액세스 토큰이 더 나은 선택입니다.
이 부여 유형은 리소스 소유자 자격 증명에 대한 직접적인 클라이언트 액세스를 필요로 하지만, 리소스 소유자 자격 증명은 단일 요청에 사용되며 액세스 토큰으로 교환됩니다. 이 부여 유형을 사용하면 클라이언트가 리소스 소유자 자격 증명을 향후 사용하기 위해 저장할 필요가 없으며, 자격 증명을 장기적인 액세스 토큰 또는 새로 고침 토큰으로 교환함으로써 이를 제거할 수 있습니다.
액세스 토큰을 요청하려면 다음 매개변수를 사용하여 /oauth/token
에 POST 요청을 보내어야 합니다.
{
"grant_type" : "password",
"username" : "user@example.com",
"password" : "secret"
}
예시 cURL 요청:
echo 'grant_type=password&username=<your_username>&password=<your_password>' > auth.txt
curl --data "@auth.txt" --request POST "https://gitlab.example.com/oauth/token"
또한, 등록된 OAuth 애플리케이션과 함께 이 부여 플로우를 사용하려면, 애플리케이션의 client_id
와 client_secret
을 사용하여 HTTP 기본 인증을 사용하십시오.
echo 'grant_type=password&username=<your_username>&password=<your_password>' > auth.txt
curl --data "@auth.txt" --user client_id:client_secret \
--request POST "https://gitlab.example.com/oauth/token"
그런 다음, 액세스 토큰이 포함된 응답을 받게 됩니다:
{
"access_token": "1f0af717251950dbd4d73154fdf0a474a5c5119adad999683f5b450c460726aa",
"token_type": "bearer",
"expires_in": 7200
}
기본적으로 액세스 토큰의 범위는 모든 읽기/쓰기 액세스를 제공하는 api
입니다.
테스트를 위해 oauth2
Ruby gem을 사용할 수 있습니다:
client = OAuth2::Client.new('the_client_id', 'the_client_secret', :site => "https://example.com")
access_token = client.password.get_token('user@example.com', 'secret')
puts access_token.token
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 젬에서 제공하는 token/info
엔드포인트를 사용하십시오. 자세한 정보는 /oauth/token/info
를 참조하세요.
토큰을 매개변수로 제공해야 합니다:
-
매개변수로:
GET https://gitlab.example.com/oauth/token/info?access_token=<OAUTH-TOKEN>
-
또는 Authorization 헤더에:
curl --header "Authorization: Bearer <OAUTH-TOKEN>" "https://gitlab.example.com/oauth/token/info"
다음은 예시 응답입니다:
{
"resource_owner_id": 1,
"scope": ["api"],
"expires_in": null,
"application": {"uid": "1cb242f495280beb4291e64bee2a17f330902e499882fe8e1e2aa875519cab33"},
"created_at": 1575890427
}
사용되지 않는 필드
scopes
필드와 expires_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 컨테이너 레지스트리.
- GitLab 패키지 레지스트리에 나열된 패키지.
- 컨테이너 레지스트리 API를 통해 레지스트리를 가져오고 목록 및 삭제하는 것은 가능합니다.