Skip to content
代码片段 群组 项目
未验证 提交 f1764ce3 编辑于 作者: Drew Blessing's avatar Drew Blessing 提交者: GitLab
浏览文件

Merge branch '443597-nwittstruck-add-oauth-application-secrets-to-api' into 'master'

Admin Token API: Add support for reading OAuth Application Secrets

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/172985



Merged-by: default avatarDrew Blessing <drew@gitlab.com>
Approved-by: default avatarAboobacker MK <akarakath@gitlab.com>
Approved-by: default avatarDrew Blessing <drew@gitlab.com>
Reviewed-by: default avatarDrew Blessing <drew@gitlab.com>
Reviewed-by: default avatarGitLab Duo <gitlab-duo@gitlab.com>
Co-authored-by: default avatarNicholas Wittstruck <1494491-nwittstruck@users.noreply.gitlab.com>
No related branches found
No related tags found
无相关合并请求
......@@ -14,6 +14,7 @@ DETAILS:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165157) in GitLab 17.5 [with a flag](../../administration/feature_flags.md) named `admin_agnostic_token_finder`. Disabled by default.
> - [Feed tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169821) in GitLab 17.6.
> - [OAuth application secrets added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/172985) in GitLab 17.7.
FLAG:
The availability of this feature is controlled by a feature flag.
......@@ -37,6 +38,7 @@ Supported tokens:
- [Personal access tokens](../../user/profile/personal_access_tokens.md)
- [Deploy tokens](../../user/project/deploy_tokens/index.md)
- [Feed tokens](../../security/tokens/index.md#feed-token)
- [OAuth application secrets](../../integration/oauth_provider.md)
```plaintext
POST /api/v4/admin/token
......
......@@ -11,7 +11,7 @@ def identify_token(plaintext)
token = ::Authn::AgnosticTokenIdentifier.token_for(plaintext, AUDIT_SOURCE)
raise ArgumentError, 'Token type not supported.' if token.blank?
token.revocable
token
end
end
......@@ -45,12 +45,11 @@ def identify_token(plaintext)
end
post 'token' do
identified_token = identify_token(params[:token])
render_api_error!({ error: 'Not found' }, :not_found) if identified_token.nil?
render_api_error!({ error: 'Not found' }, :not_found) if identified_token.revocable.nil?
status :ok
present identified_token, with: "API::Entities::#{identified_token.class.name}".constantize
present identified_token.revocable, with: identified_token.present_with
end
end
end
......
......@@ -3,10 +3,12 @@
module Authn
class AgnosticTokenIdentifier
NotFoundError = Class.new(StandardError)
UnsupportedTokenError = Class.new(StandardError)
TOKEN_TYPES = [
::Authn::Tokens::DeployToken,
::Authn::Tokens::FeedToken,
::Authn::Tokens::PersonalAccessToken
::Authn::Tokens::PersonalAccessToken,
::Authn::Tokens::OauthApplicationSecret
].freeze
def self.token_for(plaintext, source)
......
......@@ -14,6 +14,10 @@ def initialize(plaintext, source)
@source = source
end
def present_with
::API::Entities::DeployToken
end
def revoke!(current_user)
raise ::Authn::AgnosticTokenIdentifier::NotFoundError, 'Not Found' if revocable.blank?
......
......@@ -14,6 +14,10 @@ def initialize(plaintext, source)
@source = source
end
def present_with
::API::Entities::User
end
def revoke!(current_user)
raise ::Authn::AgnosticTokenIdentifier::NotFoundError, 'Not Found' if revocable.blank?
......
# frozen_string_literal:true
module Authn
module Tokens
class OauthApplicationSecret
def self.prefix?(plaintext)
prefix =
::Gitlab::DoorkeeperSecretStoring::Token::UniqueApplicationToken::OAUTH_APPLICATION_SECRET_PREFIX_FORMAT
.split('-').first
plaintext.start_with?(prefix)
end
attr_reader :revocable, :source
def initialize(plaintext, source)
@revocable = ::Doorkeeper::Application.find_by_plaintext_token(:secret, plaintext)
@source = source
end
def present_with
::API::Entities::Application
end
def revoke!(_current_user)
raise ::Authn::AgnosticTokenIdentifier::NotFoundError, 'Not Found' if revocable.blank?
raise ::Authn::AgnosticTokenIdentifier::UnsupportedTokenError, 'Revocation not supported for this token type'
end
end
end
end
......@@ -17,6 +17,10 @@ def initialize(plaintext, source)
@source = source
end
def present_with
::API::Entities::PersonalAccessToken
end
def revoke!(current_user)
raise ::Authn::AgnosticTokenIdentifier::NotFoundError, 'Not Found' if revocable.blank?
......
......@@ -9,6 +9,7 @@
let_it_be(:deploy_token) { create(:deploy_token).token }
let_it_be(:feed_token) { user.feed_token }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user).token }
let_it_be(:oauth_application_secret) { create(:oauth_application).plaintext_secret }
subject(:token) { described_class.token_for(plaintext, :group_token_revocation_service) }
......@@ -17,6 +18,7 @@
ref(:personal_access_token) | ::Authn::Tokens::PersonalAccessToken
ref(:feed_token) | ::Authn::Tokens::FeedToken
ref(:deploy_token) | ::Authn::Tokens::DeployToken
ref(:oauth_application_secret) | ::Authn::Tokens::OauthApplicationSecret
'unsupported' | NilClass
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Authn::Tokens::OauthApplicationSecret, feature_category: :system_access do
let_it_be(:user) { create(:user) }
let(:oauth_application_secret) { create(:oauth_application) }
subject(:token) { described_class.new(plaintext, :api_admin_token) }
context 'with valid oauth application secret' do
let(:plaintext) { oauth_application_secret.plaintext_secret }
let(:valid_revocable) { oauth_application_secret }
it_behaves_like 'finding the valid revocable'
describe '#revoke!' do
it 'does not support revocation yet' do
expect do
token.revoke!(user)
end.to raise_error(::Authn::AgnosticTokenIdentifier::UnsupportedTokenError,
'Revocation not supported for this token type')
end
end
end
it_behaves_like 'token handling with unsupported token type'
end
......@@ -10,6 +10,8 @@
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:deploy_token) { create(:deploy_token) }
let_it_be(:oauth_application) { create(:oauth_application) }
let(:plaintext) { nil }
let(:params) { { token: plaintext } }
......@@ -22,7 +24,8 @@
[
[ref(:personal_access_token), lazy { personal_access_token.token }],
[ref(:deploy_token), lazy { deploy_token.token }],
[ref(:user), lazy { user.feed_token }]
[ref(:user), lazy { user.feed_token }],
[ref(:oauth_application), lazy { oauth_application.plaintext_secret }]
]
end
......
......@@ -27,4 +27,10 @@
expect(token.revocable).to eq(valid_revocable)
end
end
describe '#present_with' do
it 'returns a constant that is a subclass of Grape::Entity' do
expect(token.present_with).to be <= Grape::Entity
end
end
end
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册