Skip to content

Commit

Permalink
Support Platform Access Token (#822)
Browse files Browse the repository at this point in the history
  • Loading branch information
RobiNino authored Oct 3, 2023
1 parent 3bb7a42 commit 568b467
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 37 deletions.
52 changes: 40 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@
- [Cleaning Unreferenced Git LFS Files from Artifactory](#cleaning-unreferenced-git-lfs-files-from-artifactory)
- [Executing AQLs](#executing-aqls)
- [Reading Files in Artifactory](#reading-files-in-artifactory)
- [Creating an Access Token](#creating-an-access-token)
- [Fetching Access Tokens](#fetching-access-tokens)
- [Fetching Access Tokens of a User](#fetching-access-tokens-of-a-user)
- [Refreshing an Access Token](#refreshing-an-access-token)
- [Revoking an Access Token](#revoking-an-access-token)
- [Creating an Artifactory Access Token](#creating-an-artifactory-access-token)
- [Fetching Artifactory Access Tokens](#fetching-artifactory-access-tokens)
- [Fetching Artifactory Access Tokens of a User](#fetching-artifactory-access-tokens-of-a-user)
- [Refreshing an Artifactory Access Token](#refreshing-an-artifactory-access-token)
- [Revoking an Artifactory Access Token](#revoking-an-artifactory-access-token)
- [Create API Key](#create-api-key)
- [Regenerate API Key](#regenerate-api-key)
- [Get API Key](#get-api-key)
Expand Down Expand Up @@ -111,13 +111,15 @@
- [Getting a Project](#getting-a-project)
- [Getting all Projects](#getting-all-projects)
- [Assigning Repository to Project](#assigning-repository-to-project)
- [Unassigning Repository from Project](#unassigning-repository-from-project)
- [Un-assigning Repository from Project](#un-assigning-repository-from-project)
- [Get all groups assigned to a project](#get-all-groups-assigned-to-a-project)
- [Get a specific group assigned to a project](#get-a-specific-group-assigned-to-a-project)
- [Add or update a group assigned to a project](#add-or-update-a-group-assigned-to-a-project)
- [Remove a group from a project](#remove-a-group-from-a-project)
- [Send Web Login Authentication Request](#send-web-login-authentication-request)
- [Get Web Login Authentication Token](#get-web-login-authentication-token)
- [Creating an Access Token](#creating-an-access-token)
- [Refreshing an Access Token](#refreshing-an-access-token)
- [Distribution APIs](#distribution-apis)
- [Creating Distribution Service Manager](#creating-distribution-service-manager)
- [Creating Distribution Details](#creating-distribution-details)
Expand Down Expand Up @@ -725,7 +727,7 @@ rtManager.Aql(aql string)
rtManager.ReadRemoteFile(FilePath string)
```

#### Creating an Access Token
#### Creating an Artifactory Access Token

```go
params := services.NewCreateTokenParams()
Expand All @@ -739,19 +741,19 @@ params.Audience = "jfrt@<serviceID1> jfrt@<serviceID2>"
results, err := rtManager.CreateToken(params)
```

#### Fetching Access Tokens
#### Fetching Artifactory Access Tokens

```go
results, err := rtManager.GetTokens()
```

#### Fetching Access Tokens of a User
#### Fetching Artifactory Access Tokens of a User

```g
results, err := rtManager.GetUserTokens(username)
```

#### Refreshing an Access Token
#### Refreshing an Artifactory Access Token

```go
params := services.NewRefreshTokenParams()
Expand All @@ -762,7 +764,7 @@ params.Token.ExpiresIn = 3600
results, err := rtManager.RefreshToken(params)
```

#### Revoking an Access Token
#### Revoking an Artifactory Access Token

```go
params := services.NewRevokeTokenParams()
Expand Down Expand Up @@ -1467,7 +1469,7 @@ err = accessManager.GetAllProjects()
err = accessManager.AssignRepoToProject("repoName", "tstprj", true)
```

#### Unassigning Repository from Project
#### Un-assigning Repository from Project

```go
err = accessManager.AssignRepoToProject("repoName")
Expand Down Expand Up @@ -1515,6 +1517,32 @@ uuid := "09b34617-b48a-455d-8b05-25a6989fb76a"
err = accessManager.GetLoginAuthenticationToken(uuid)
```

#### Creating an Access Token

```go
params := CreateTokenParams{}
params.Scope = "applied-permissions/user"
params.Username = "my-user"
params.ExpiresIn = 12345 // nil = system default, 0 = no expiry.
params.Refreshable = true
params.Audience = "jfrt@<serviceID1>"
reference := true
params.IncludeReferenceToken = &reference
params.ProjectKey = "my-project"
params.Description = "my-token"

results, err := accessManager.CreateToken(params)
```

#### Refreshing an Access Token

```go
params := accessServices.CreateTokenParams{}
params.RefreshToken = "<refresh token>"

results, err := accessManager.RefreshToken(params)
```

## Distribution APIs

### Creating Distribution Service Manager
Expand Down
41 changes: 22 additions & 19 deletions access/services/accesstoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ type TokenService struct {

type CreateTokenParams struct {
auth.CommonTokenParams
IncludeReferenceToken *bool `json:"include_reference_token,omitempty"`
IncludeReferenceToken *bool `json:"include_reference_token,omitempty"`
Username string `json:"username,omitempty"`
ProjectKey string `json:"project_key,omitempty"`
Description string `json:"description,omitempty"`
}

func NewCreateTokenParams(params CreateTokenParams) CreateTokenParams {
Expand All @@ -37,22 +40,19 @@ func (ps *TokenService) CreateAccessToken(params CreateTokenParams) (auth.Create
return ps.createAccessToken(params)
}

func (ps *TokenService) RefreshAccessToken(token CreateTokenParams) (auth.CreateTokenResponseData, error) {
param, err := createRefreshTokenRequestParams(token)
func (ps *TokenService) RefreshAccessToken(params CreateTokenParams) (auth.CreateTokenResponseData, error) {
refreshParams, err := prepareForRefresh(params)
if err != nil {
return auth.CreateTokenResponseData{}, err
}
return ps.createAccessToken(*param)
return ps.createAccessToken(*refreshParams)
}

// createAccessToken is used to create & refresh access tokens.
func (ps *TokenService) createAccessToken(params CreateTokenParams) (auth.CreateTokenResponseData, error) {
// Set the request headers
tokenInfo := auth.CreateTokenResponseData{}
func (ps *TokenService) createAccessToken(params CreateTokenParams) (tokenInfo auth.CreateTokenResponseData, err error) {
httpDetails := ps.ServiceDetails.CreateHttpClientDetails()
utils.SetContentType("application/json", &httpDetails.Headers)
err := ps.addAccessTokenAuthorizationHeader(params, &httpDetails)
if err != nil {
if err = ps.handleUnauthenticated(params, &httpDetails); err != nil {
return tokenInfo, err
}
requestContent, err := json.Marshal(params)
Expand All @@ -71,23 +71,26 @@ func (ps *TokenService) createAccessToken(params CreateTokenParams) (auth.Create
return tokenInfo, errorutils.CheckError(err)
}

func (ps *TokenService) addAccessTokenAuthorizationHeader(params CreateTokenParams, httpDetails *httputils.HttpClientDetails) error {
access := ps.ServiceDetails.GetAccessToken()
if access == "" {
access = params.AccessToken
func (ps *TokenService) handleUnauthenticated(params CreateTokenParams, httpDetails *httputils.HttpClientDetails) error {
// Creating access tokens using username and password is available since Artifactory 7.63.2,
// by enabling "Enable Token Generation via API" in the UI.
if httpDetails.AccessToken != "" || (httpDetails.User != "" && httpDetails.Password != "") {
return nil
}
if access == "" {
return errorutils.CheckErrorf("failed: adding accessToken authorization, but No accessToken was provided. ")
// Use token from params if provided.
if params.AccessToken != "" {
httpDetails.AccessToken = params.AccessToken
return nil
}
utils.AddHeader("Authorization", fmt.Sprintf("Bearer %s", access), &httpDetails.Headers)
return nil
return errorutils.CheckErrorf("cannot create access token without credentials")
}

func createRefreshTokenRequestParams(p CreateTokenParams) (*CreateTokenParams, error) {
func prepareForRefresh(p CreateTokenParams) (*CreateTokenParams, error) {
// Validate provided parameters
if p.RefreshToken == "" {
return nil, errorutils.CheckErrorf("error: trying to refresh token, but 'refresh_token' field wasn't provided. ")
return nil, errorutils.CheckErrorf("trying to refresh token, but 'refresh_token' field wasn't provided")
}

params := NewCreateTokenParams(p)
// Set refresh required parameters
params.GrantType = "refresh_token"
Expand Down
3 changes: 2 additions & 1 deletion auth/authutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import (
type CreateTokenResponseData struct {
CommonTokenParams
ReferenceToken string `json:"reference_token,omitempty"`
TokenId string `json:"token_id,omitempty"`
}

type CommonTokenParams struct {
Scope string `json:"scope,omitempty"`
AccessToken string `json:"access_token,omitempty"`
ExpiresIn int `json:"expires_in,omitempty"`
ExpiresIn *uint `json:"expires_in,omitempty"`
TokenType string `json:"token_type,omitempty"`
Refreshable *bool `json:"refreshable,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
Expand Down
10 changes: 5 additions & 5 deletions tests/accesstokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func testCreateRefreshableToken(t *testing.T) {
assert.NotEqual(t, "", token.AccessToken, "Access token is empty")
assert.NotEqual(t, tokenParams.AccessToken, token.AccessToken, "New access token is identical to original one")
assert.NotEqual(t, "", token.RefreshToken, "Refresh token is empty")
assert.Equal(t, testExpiredInSeconds, token.ExpiresIn)
assert.EqualValues(t, testExpiredInSeconds, *token.ExpiresIn)
assert.Empty(t, token.ReferenceToken)
}

Expand All @@ -36,7 +36,7 @@ func testAccessTokenWithReference(t *testing.T) {
assert.NotEqual(t, "", token.AccessToken, "Access token is empty")
assert.NotEqual(t, tokenParams.AccessToken, token.AccessToken, "New access token is identical to original one")
assert.NotEqual(t, "", token.RefreshToken, "Refresh token is empty")
assert.Equal(t, testExpiredInSeconds, token.ExpiresIn)
assert.EqualValues(t, testExpiredInSeconds, *token.ExpiresIn)
assert.NotEmpty(t, token.ReferenceToken)
}

Expand All @@ -52,13 +52,13 @@ func testRefreshTokenTest(t *testing.T) {
// Validate
assert.NotEqual(t, token.AccessToken, newToken.AccessToken, "New access token is identical to original one")
assert.NotEqual(t, token.RefreshToken, newToken.RefreshToken, "New refresh token is identical to original one")
assert.Equal(t, token.ExpiresIn, newToken.ExpiresIn, "New access token's expiration is different from original one")
assert.EqualValues(t, token.ExpiresIn, newToken.ExpiresIn, "New access token's expiration is different from original one")
assert.Empty(t, token.ReferenceToken)
}

func createRefreshableAccessTokenParams(expiredIn int) services.CreateTokenParams {
func createRefreshableAccessTokenParams(expiredIn uint) services.CreateTokenParams {
tokenParams := services.CreateTokenParams{}
tokenParams.ExpiresIn = expiredIn
tokenParams.ExpiresIn = &expiredIn
tokenParams.Refreshable = utils.Pointer(true)
tokenParams.Audience = "*@*"
return tokenParams
Expand Down

0 comments on commit 568b467

Please sign in to comment.