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