Skip to content

Commit

Permalink
Merge pull request #6 from DrDaveD/add-refresh-token-opt
Browse files Browse the repository at this point in the history
Add refresh_token option to creds write
  • Loading branch information
impl committed Apr 6, 2020
2 parents bb7404c + a74f7e4 commit c91611f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 15 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ access_token nLlBg9Lmd7n1X96bw/xcW9HvyOHzxj19z3zXKv0XXxr8eLjQSerf4iyPDRCucSHQ
Note that the client secret and refresh token are never exposed to Vault
clients.

Alternatively, if a refresh token is obtained in some other way you can
skip the auth_code_url step and pass the token directly to the creds
write instead of the response code:

```console
$ vault write oauth2/bitbucket/creds/my-user-tokens refresh_token=eyJhbGciOiJub25lIn0.eyJqdGkiOiI4YTE0NDRjMi0wYjQxLTRiZDUtODI3My0yZDBkMDczODQ4MDAifQ.
Success! Data written to: oauth2/bitbucket/creds/my-user-tokens
```

## Endpoints

### `config`
Expand Down Expand Up @@ -117,8 +126,9 @@ application.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|----------|
| `code` | The response code to exchange for a full token. | String | None | Yes |
| `code` | The response code to exchange for a full token. | String | None | Either this or `refresh_token` |
| `redirect_url` | The same redirect URL as specified in the authorization code URL. | String | None | Refer to provider documentation |
| `refresh_token` | A refresh token retrieved from the provider by some means external to this plugin. | String | None | Either this or `code` |

#### `DELETE` (`delete`)

Expand Down
44 changes: 30 additions & 14 deletions pkg/backend/path_creds.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,34 @@ func (b *backend) credsUpdateOperation(ctx context.Context, req *logical.Request

key := credKey(data.Get("name").(string))

code, ok := data.GetOk("code")
if !ok {
return logical.ErrorResponse("missing code"), nil
}
var tok *oauth2.Token

cb := p.NewExchangeConfigBuilder(c.ClientID, c.ClientSecret)

if redirectURL, ok := data.GetOk("redirect_url"); ok {
cb = cb.WithRedirectURL(redirectURL.(string))
}

tok, err := cb.Build().Exchange(ctx, code.(string))
if _, ok := err.(*oauth2.RetrieveError); ok {
return logical.ErrorResponse("invalid code"), nil
} else if err != nil {
return nil, err
if code, ok := data.GetOk("code"); ok {
if _, ok := data.GetOk("refresh_token"); ok {
return logical.ErrorResponse("cannot use both code and refresh_token"), nil
}

if redirectURL, ok := data.GetOk("redirect_url"); ok {
cb = cb.WithRedirectURL(redirectURL.(string))
}

tok, err = cb.Build().Exchange(ctx, code.(string))
if _, ok := err.(*oauth2.RetrieveError); ok {
return logical.ErrorResponse("invalid code"), nil
} else if err != nil {
return nil, err
}
} else if refreshToken, ok := data.GetOk("refresh_token"); ok {
tok, err = cb.Build().TokenSource(ctx, &oauth2.Token{RefreshToken: refreshToken.(string)}).Token()
if _, ok := err.(*oauth2.RetrieveError); ok {
return logical.ErrorResponse("invalid refresh_token"), nil
} else if err != nil {
return nil, err
}
// tok now contains a refresh token and an access token
} else {
return logical.ErrorResponse("missing code or refresh_token"), nil
}

b.credMut.Lock()
Expand Down Expand Up @@ -128,6 +140,10 @@ var credsFields = map[string]*framework.FieldSchema{
Type: framework.TypeString,
Description: "Specifies the redirect URL to provide when exchanging (required by some services and must be equivalent to the redirect URL provided to the authorization code URL).",
},
"refresh_token": {
Type: framework.TypeString,
Description: "Specifies a refresh token retrieved from the provider by some means external to this plugin.",
},
}

const credsHelpSynopsis = `
Expand Down

0 comments on commit c91611f

Please sign in to comment.