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  }