| package tokens |
| |
| import "github.com/gophercloud/gophercloud" |
| |
| // Scope allows a created token to be limited to a specific domain or project. |
| type Scope struct { |
| ProjectID string |
| ProjectName string |
| DomainID string |
| DomainName string |
| } |
| |
| // AuthOptionsBuilder provides the ability for extensions to add additional |
| // parameters to AuthOptions. Extensions must satisfy all required methods. |
| type AuthOptionsBuilder interface { |
| // ToTokenV3CreateMap assembles the Create request body, returning an error |
| // if parameters are missing or inconsistent. |
| ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error) |
| ToTokenV3ScopeMap() (map[string]interface{}, error) |
| CanReauth() bool |
| } |
| |
| // AuthOptions represents options for authenticating a user. |
| type AuthOptions struct { |
| // IdentityEndpoint specifies the HTTP endpoint that is required to work with |
| // the Identity API of the appropriate version. While it's ultimately needed |
| // by all of the identity services, it will often be populated by a |
| // provider-level function. |
| IdentityEndpoint string `json:"-"` |
| |
| // Username is required if using Identity V2 API. Consult with your provider's |
| // control panel to discover your account's username. In Identity V3, either |
| // UserID or a combination of Username and DomainID or DomainName are needed. |
| Username string `json:"username,omitempty"` |
| UserID string `json:"id,omitempty"` |
| |
| Password string `json:"password,omitempty"` |
| |
| // At most one of DomainID and DomainName must be provided if using Username |
| // with Identity V3. Otherwise, either are optional. |
| DomainID string `json:"-"` |
| DomainName string `json:"name,omitempty"` |
| |
| // AllowReauth should be set to true if you grant permission for Gophercloud |
| // to cache your credentials in memory, and to allow Gophercloud to attempt |
| // to re-authenticate automatically if/when your token expires. If you set |
| // it to false, it will not cache these settings, but re-authentication will |
| // not be possible. This setting defaults to false. |
| AllowReauth bool `json:"-"` |
| |
| // TokenID allows users to authenticate (possibly as another user) with an |
| // authentication token ID. |
| TokenID string `json:"-"` |
| |
| // Authentication through Application Credentials requires supplying name, project and secret |
| // For project we can use TenantID |
| ApplicationCredentialID string `json:"-"` |
| ApplicationCredentialName string `json:"-"` |
| ApplicationCredentialSecret string `json:"-"` |
| |
| Scope Scope `json:"-"` |
| } |
| |
| // ToTokenV3CreateMap builds a request body from AuthOptions. |
| func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) { |
| gophercloudAuthOpts := gophercloud.AuthOptions{ |
| Username: opts.Username, |
| UserID: opts.UserID, |
| Password: opts.Password, |
| DomainID: opts.DomainID, |
| DomainName: opts.DomainName, |
| AllowReauth: opts.AllowReauth, |
| TokenID: opts.TokenID, |
| ApplicationCredentialID: opts.ApplicationCredentialID, |
| ApplicationCredentialName: opts.ApplicationCredentialName, |
| ApplicationCredentialSecret: opts.ApplicationCredentialSecret, |
| } |
| |
| return gophercloudAuthOpts.ToTokenV3CreateMap(scope) |
| } |
| |
| // ToTokenV3CreateMap builds a scope request body from AuthOptions. |
| func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) { |
| scope := gophercloud.AuthScope(opts.Scope) |
| |
| gophercloudAuthOpts := gophercloud.AuthOptions{ |
| Scope: &scope, |
| DomainID: opts.DomainID, |
| DomainName: opts.DomainName, |
| } |
| |
| return gophercloudAuthOpts.ToTokenV3ScopeMap() |
| } |
| |
| func (opts *AuthOptions) CanReauth() bool { |
| return opts.AllowReauth |
| } |
| |
| func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string { |
| return map[string]string{ |
| "X-Subject-Token": subjectToken, |
| } |
| } |
| |
| // Create authenticates and either generates a new token, or changes the Scope |
| // of an existing token. |
| func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { |
| scope, err := opts.ToTokenV3ScopeMap() |
| if err != nil { |
| r.Err = err |
| return |
| } |
| |
| b, err := opts.ToTokenV3CreateMap(scope) |
| if err != nil { |
| r.Err = err |
| return |
| } |
| |
| resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ |
| MoreHeaders: map[string]string{"X-Auth-Token": ""}, |
| }) |
| r.Err = err |
| if resp != nil { |
| r.Header = resp.Header |
| } |
| return |
| } |
| |
| // Get validates and retrieves information about another token. |
| func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { |
| resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{ |
| MoreHeaders: subjectTokenHeaders(c, token), |
| OkCodes: []int{200, 203}, |
| }) |
| if resp != nil { |
| r.Err = err |
| r.Header = resp.Header |
| } |
| return |
| } |
| |
| // Validate determines if a specified token is valid or not. |
| func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { |
| resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{ |
| MoreHeaders: subjectTokenHeaders(c, token), |
| OkCodes: []int{200, 204, 404}, |
| }) |
| if err != nil { |
| return false, err |
| } |
| |
| return resp.StatusCode == 200 || resp.StatusCode == 204, nil |
| } |
| |
| // Revoke immediately makes specified token invalid. |
| func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { |
| _, r.Err = c.Delete(tokenURL(c), &gophercloud.RequestOpts{ |
| MoreHeaders: subjectTokenHeaders(c, token), |
| }) |
| return |
| } |