go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/oauth/state.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package oauth
     9  
    10  import (
    11  	"bytes"
    12  	"encoding/base64"
    13  	"encoding/gob"
    14  )
    15  
    16  // State is the oauth state.
    17  type State struct {
    18  	// Token is a plaintext random token.
    19  	Token string
    20  	// SecureToken is the hashed version of the token.
    21  	// If a key is set, it validates that our app created the oauth state.
    22  	SecureToken string
    23  	// RedirectURI is the redirect uri.
    24  	RedirectURI string
    25  	// Extra includes other state you might need to encode.
    26  	Extra map[string]interface{}
    27  }
    28  
    29  // DeserializeState deserializes the oauth state.
    30  func DeserializeState(raw string) (state State, err error) {
    31  	var corpus []byte
    32  	corpus, err = base64.RawURLEncoding.DecodeString(raw)
    33  	if err != nil {
    34  		return
    35  	}
    36  	buffer := bytes.NewBuffer(corpus)
    37  	err = gob.NewDecoder(buffer).Decode(&state)
    38  	return
    39  }
    40  
    41  // MustSerializeState serializes a state value but panics if there is an error.
    42  func MustSerializeState(state State) string {
    43  	output, err := SerializeState(state)
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  	return output
    48  }
    49  
    50  // SerializeState serializes the oauth state.
    51  func SerializeState(state State) (output string, err error) {
    52  	buffer := new(bytes.Buffer)
    53  	err = gob.NewEncoder(buffer).Encode(state)
    54  	if err != nil {
    55  		return
    56  	}
    57  	output = base64.RawURLEncoding.EncodeToString(buffer.Bytes())
    58  	return
    59  }
    60  
    61  // StateOption is an option for state objects
    62  type StateOption func(*State)
    63  
    64  // OptStateSecureToken sets the secure token on the state.
    65  func OptStateSecureToken(secureToken string) StateOption {
    66  	return func(s *State) {
    67  		s.SecureToken = secureToken
    68  	}
    69  }
    70  
    71  // OptStateRedirectURI sets the redirect uri on the stae.
    72  func OptStateRedirectURI(redirectURI string) StateOption {
    73  	return func(s *State) {
    74  		s.RedirectURI = redirectURI
    75  	}
    76  }
    77  
    78  // OptStateExtra sets the redirect uri on the stae.
    79  func OptStateExtra(key string, value interface{}) StateOption {
    80  	return func(s *State) {
    81  		if s.Extra == nil {
    82  			s.Extra = make(map[string]interface{})
    83  		}
    84  		s.Extra[key] = value
    85  	}
    86  }