Skip to content

Commit

Permalink
Support JFrog Access Token
Browse files Browse the repository at this point in the history
  • Loading branch information
RobiNino committed Sep 7, 2023
1 parent 2c3c91d commit f15076b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 32 deletions.
53 changes: 27 additions & 26 deletions access/services/accesstoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ 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 {
return CreateTokenParams{CommonTokenParams: params.CommonTokenParams, IncludeReferenceToken: params.IncludeReferenceToken}
func NewCreateTokenParams() CreateTokenParams {
return CreateTokenParams{}
}

func NewTokenService(client *jfroghttpclient.JfrogHttpClient) *TokenService {
Expand All @@ -36,22 +39,18 @@ 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)
if err != nil {
func (ps *TokenService) RefreshAccessToken(params CreateTokenParams) (auth.CreateTokenResponseData, error) {
if err := prepareForRefresh(&params); err != nil {
return auth.CreateTokenResponseData{}, err
}
return ps.createAccessToken(*param)
return ps.createAccessToken(params)
}

// 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 @@ -70,27 +69,29 @@ 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) error {
var trueValue = true
// Validate provided parameters
if p.RefreshToken == "" {
return nil, errorutils.CheckErrorf("error: trying to refresh token, but 'refresh_token' field wasn't provided. ")
return errorutils.CheckErrorf("error: trying to refresh token, but 'refresh_token' field wasn't provided. ")
}
params := NewCreateTokenParams(p)

// Set refresh required parameters
params.GrantType = "refresh_token"
params.Refreshable = &trueValue
return &params, nil
p.GrantType = "refresh_token"
p.Refreshable = &trueValue
return nil
}
2 changes: 1 addition & 1 deletion auth/authutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type CreateTokenResponseData struct {
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 @@ -23,7 +23,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 @@ -35,7 +35,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 @@ -51,13 +51,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 = &trueValue
tokenParams.Audience = "*@*"
return tokenParams
Expand Down

0 comments on commit f15076b

Please sign in to comment.