github.com/gophercloud/gophercloud@v1.11.0/openstack/identity/v3/tokens/requests.go (about) 1 package tokens 2 3 import "github.com/gophercloud/gophercloud" 4 5 // Scope allows a created token to be limited to a specific domain or project. 6 type Scope struct { 7 ProjectID string 8 ProjectName string 9 DomainID string 10 DomainName string 11 System bool 12 } 13 14 // AuthOptionsBuilder provides the ability for extensions to add additional 15 // parameters to AuthOptions. Extensions must satisfy all required methods. 16 type AuthOptionsBuilder interface { 17 // ToTokenV3CreateMap assembles the Create request body, returning an error 18 // if parameters are missing or inconsistent. 19 ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error) 20 ToTokenV3HeadersMap(map[string]interface{}) (map[string]string, error) 21 ToTokenV3ScopeMap() (map[string]interface{}, error) 22 CanReauth() bool 23 } 24 25 // AuthOptions represents options for authenticating a user. 26 type AuthOptions struct { 27 // IdentityEndpoint specifies the HTTP endpoint that is required to work with 28 // the Identity API of the appropriate version. While it's ultimately needed 29 // by all of the identity services, it will often be populated by a 30 // provider-level function. 31 IdentityEndpoint string `json:"-"` 32 33 // Username is required if using Identity V2 API. Consult with your provider's 34 // control panel to discover your account's username. In Identity V3, either 35 // UserID or a combination of Username and DomainID or DomainName are needed. 36 Username string `json:"username,omitempty"` 37 UserID string `json:"id,omitempty"` 38 39 Password string `json:"password,omitempty"` 40 41 // Passcode is used in TOTP authentication method 42 Passcode string `json:"passcode,omitempty"` 43 44 // At most one of DomainID and DomainName must be provided if using Username 45 // with Identity V3. Otherwise, either are optional. 46 DomainID string `json:"-"` 47 DomainName string `json:"name,omitempty"` 48 49 // AllowReauth should be set to true if you grant permission for Gophercloud 50 // to cache your credentials in memory, and to allow Gophercloud to attempt 51 // to re-authenticate automatically if/when your token expires. If you set 52 // it to false, it will not cache these settings, but re-authentication will 53 // not be possible. This setting defaults to false. 54 AllowReauth bool `json:"-"` 55 56 // TokenID allows users to authenticate (possibly as another user) with an 57 // authentication token ID. 58 TokenID string `json:"-"` 59 60 // Authentication through Application Credentials requires supplying name, project and secret 61 // For project we can use TenantID 62 ApplicationCredentialID string `json:"-"` 63 ApplicationCredentialName string `json:"-"` 64 ApplicationCredentialSecret string `json:"-"` 65 66 Scope Scope `json:"-"` 67 } 68 69 // ToTokenV3CreateMap builds a request body from AuthOptions. 70 func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) { 71 gophercloudAuthOpts := gophercloud.AuthOptions{ 72 Username: opts.Username, 73 UserID: opts.UserID, 74 Password: opts.Password, 75 Passcode: opts.Passcode, 76 DomainID: opts.DomainID, 77 DomainName: opts.DomainName, 78 AllowReauth: opts.AllowReauth, 79 TokenID: opts.TokenID, 80 ApplicationCredentialID: opts.ApplicationCredentialID, 81 ApplicationCredentialName: opts.ApplicationCredentialName, 82 ApplicationCredentialSecret: opts.ApplicationCredentialSecret, 83 } 84 85 return gophercloudAuthOpts.ToTokenV3CreateMap(scope) 86 } 87 88 // ToTokenV3ScopeMap builds a scope request body from AuthOptions. 89 func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) { 90 scope := gophercloud.AuthScope(opts.Scope) 91 92 gophercloudAuthOpts := gophercloud.AuthOptions{ 93 Scope: &scope, 94 DomainID: opts.DomainID, 95 DomainName: opts.DomainName, 96 } 97 98 return gophercloudAuthOpts.ToTokenV3ScopeMap() 99 } 100 101 func (opts *AuthOptions) CanReauth() bool { 102 if opts.Passcode != "" { 103 // cannot reauth using TOTP passcode 104 return false 105 } 106 107 return opts.AllowReauth 108 } 109 110 // ToTokenV3HeadersMap allows AuthOptions to satisfy the AuthOptionsBuilder 111 // interface in the v3 tokens package. 112 func (opts *AuthOptions) ToTokenV3HeadersMap(map[string]interface{}) (map[string]string, error) { 113 return nil, nil 114 } 115 116 func subjectTokenHeaders(subjectToken string) map[string]string { 117 return map[string]string{ 118 "X-Subject-Token": subjectToken, 119 } 120 } 121 122 // Create authenticates and either generates a new token, or changes the Scope 123 // of an existing token. 124 func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { 125 scope, err := opts.ToTokenV3ScopeMap() 126 if err != nil { 127 r.Err = err 128 return 129 } 130 131 b, err := opts.ToTokenV3CreateMap(scope) 132 if err != nil { 133 r.Err = err 134 return 135 } 136 137 resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ 138 OmitHeaders: []string{"X-Auth-Token"}, 139 }) 140 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 141 return 142 } 143 144 // Get validates and retrieves information about another token. 145 func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { 146 resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{ 147 MoreHeaders: subjectTokenHeaders(token), 148 OkCodes: []int{200, 203}, 149 }) 150 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 151 return 152 } 153 154 // Validate determines if a specified token is valid or not. 155 func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { 156 resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{ 157 MoreHeaders: subjectTokenHeaders(token), 158 OkCodes: []int{200, 204, 404}, 159 }) 160 if err != nil { 161 return false, err 162 } 163 164 return resp.StatusCode == 200 || resp.StatusCode == 204, nil 165 } 166 167 // Revoke immediately makes specified token invalid. 168 func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { 169 resp, err := c.Delete(tokenURL(c), &gophercloud.RequestOpts{ 170 MoreHeaders: subjectTokenHeaders(token), 171 }) 172 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 173 return 174 }