github.com/Axway/agent-sdk@v1.1.101/pkg/authz/oauth/keypairauthenticator.go (about)

     1  package oauth
     2  
     3  import (
     4  	"crypto/rsa"
     5  	"fmt"
     6  	"net/url"
     7  	"time"
     8  
     9  	"github.com/Axway/agent-sdk/pkg/util"
    10  	"github.com/golang-jwt/jwt"
    11  	"github.com/google/uuid"
    12  )
    13  
    14  const (
    15  	SigningMethodRS256 = "RS256"
    16  	SigningMethodRS384 = "RS384"
    17  	SigningMethodRS512 = "RS512"
    18  
    19  	SigningMethodES256 = "ES256"
    20  	SigningMethodES384 = "ES384"
    21  	SigningMethodES512 = "ES512"
    22  
    23  	SigningMethodPS256 = "PS256"
    24  	SigningMethodPS384 = "PS384"
    25  	SigningMethodPS512 = "PS512"
    26  
    27  	SigningMethodHS256 = "HS256"
    28  	SigningMethodHS384 = "HS384"
    29  	SigningMethodHS512 = "HS512"
    30  )
    31  
    32  var signingMethodMap = map[string]jwt.SigningMethod{
    33  	SigningMethodRS256: jwt.SigningMethodRS256,
    34  	SigningMethodRS384: jwt.SigningMethodRS384,
    35  	SigningMethodRS512: jwt.SigningMethodRS512,
    36  	SigningMethodES256: jwt.SigningMethodES256,
    37  	SigningMethodES384: jwt.SigningMethodES384,
    38  	SigningMethodES512: jwt.SigningMethodES512,
    39  	SigningMethodPS256: jwt.SigningMethodPS256,
    40  	SigningMethodPS384: jwt.SigningMethodPS384,
    41  	SigningMethodPS512: jwt.SigningMethodPS512,
    42  	SigningMethodHS256: jwt.SigningMethodHS256,
    43  	SigningMethodHS384: jwt.SigningMethodHS384,
    44  	SigningMethodHS512: jwt.SigningMethodHS512,
    45  }
    46  
    47  type keyPairAuthenticator struct {
    48  	clientID      string
    49  	issuer        string
    50  	aud           string
    51  	privateKey    *rsa.PrivateKey
    52  	publicKey     []byte
    53  	scope         string
    54  	signingMethod string
    55  }
    56  
    57  func getSigningMethod(signingMethod string, defaultSigningMethod jwt.SigningMethod) jwt.SigningMethod {
    58  	sm, ok := signingMethodMap[signingMethod]
    59  	if !ok {
    60  		return defaultSigningMethod
    61  	}
    62  	return sm
    63  }
    64  
    65  // prepareInitialToken prepares a token for an access request
    66  func (p *keyPairAuthenticator) prepareInitialToken(kid string) (string, error) {
    67  	now := time.Now()
    68  	if p.issuer == "" {
    69  		p.issuer = fmt.Sprintf("%s:%s", assertionTypeJWT, p.clientID)
    70  	}
    71  	token := jwt.NewWithClaims(getSigningMethod(p.signingMethod, jwt.SigningMethodRS256), jwt.StandardClaims{
    72  		Issuer:    p.issuer,
    73  		Subject:   p.clientID,
    74  		Audience:  p.aud,
    75  		ExpiresAt: now.Add(60*time.Second).UnixNano() / 1e9,
    76  		IssuedAt:  now.UnixNano() / 1e9,
    77  		Id:        uuid.New().String(),
    78  	})
    79  
    80  	token.Header["kid"] = kid
    81  
    82  	requestToken, err := token.SignedString(p.privateKey)
    83  	if err != nil {
    84  		return "", err
    85  	}
    86  
    87  	return requestToken, nil
    88  }
    89  
    90  func (p *keyPairAuthenticator) prepareRequest() (url.Values, map[string]string, error) {
    91  	kid, err := util.ComputeKIDFromDER(p.publicKey)
    92  	if err != nil {
    93  		return nil, nil, err
    94  	}
    95  
    96  	requestToken, err := p.prepareInitialToken(kid)
    97  	if err != nil {
    98  		return nil, nil, err
    99  	}
   100  
   101  	v := url.Values{
   102  		metaGrantType:           []string{GrantTypeClientCredentials},
   103  		metaClientAssertionType: []string{assertionTypeJWT},
   104  		metaClientAssertion:     []string{requestToken},
   105  	}
   106  
   107  	if p.scope != "" {
   108  		v.Add(metaScope, p.scope)
   109  	}
   110  	return v, nil, nil
   111  }