-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Utility for printing JWT #9
Changes from all commits
b9b7a19
2537889
5cac46a
0da1cb8
f09fa4d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"os" | ||
"time" | ||
|
||
"github.com/nicheinc/sfdcclient/v2" | ||
"github.com/peterbourgon/ff/v3" | ||
) | ||
|
||
func main() { | ||
|
||
var ( | ||
sandbox bool | ||
salesforceInstanceID string | ||
privateKeyFile string | ||
consumerKey string | ||
username string | ||
) | ||
|
||
flag.BoolVar(&sandbox, "sandbox", false, "Whether the instance the client connects to, is a sandbox or not") | ||
flag.StringVar(&salesforceInstanceID, "salesforce.instanceID", "", "Salesforce instance URL") | ||
flag.StringVar(&privateKeyFile, "salesforce.app.cert.privateKey", "", "Path to the private key file") | ||
flag.StringVar(&consumerKey, "salesforce.app.consumerKey", "", "Connected app consumer key") | ||
flag.StringVar(&username, "salesforce.app.username", "", "Username using the connected app") | ||
|
||
if err := ff.Parse(flag.CommandLine, os.Args[1:], ff.WithEnvVarNoPrefix()); err != nil { | ||
log.Fatalf("Error parsing flags: %s", err) | ||
} | ||
|
||
// Read your private key into memory | ||
privateKeyBytes, err := os.ReadFile(privateKeyFile) | ||
if err != nil { | ||
log.Fatalf("Error reading private key: %s", err) | ||
} | ||
|
||
client, err := sfdcclient.NewClientWithJWTBearer( | ||
sandbox, // whether the instance the client connects to, is a sandbox or not | ||
salesforceInstanceID, // the salesforce instance URL | ||
consumerKey, // the connected app consumer key | ||
username, // the username using the connected app | ||
privateKeyBytes, | ||
3*time.Second, // request timeout for the OAuth new token HTTP request (3 minute max) | ||
http.Client{ // underlying HTTP client making all HTTP calls | ||
Timeout: 5 * time.Second, | ||
}, | ||
) | ||
if err != nil { | ||
log.Fatalf("Error initializing connected app salesforce client: %s", err) | ||
} | ||
|
||
jwt, err := client.JWT() | ||
if err != nil { | ||
log.Fatalf("Error getting JWT: %s", err) | ||
} | ||
fmt.Printf("%s\n", jwt) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
module github.com/nicheinc/sfdcclient | ||
module github.com/nicheinc/sfdcclient/v2 | ||
|
||
go 1.15 | ||
go 1.18 | ||
|
||
require github.com/dgrijalva/jwt-go v3.2.0+incompatible | ||
require ( | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible | ||
github.com/peterbourgon/ff/v3 v3.4.0 | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | ||
github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= | ||
github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,7 @@ type jwtBearer struct { | |
errMutex *sync.RWMutex | ||
} | ||
|
||
func NewClientWithJWTBearer(sandbox bool, instanceURL, consumerKey, username string, privateKey []byte, tokenDuration time.Duration, httpClient http.Client) (Client, error) { | ||
func NewClientWithJWTBearer(sandbox bool, instanceURL, consumerKey, username string, privateKey []byte, tokenDuration time.Duration, httpClient http.Client) (*jwtBearer, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed this return type from an interface type ( I didn't think it was particularly valuable to also make sure that the returned struct type was exported, as I'm not sure what the use would be for other modules to be able to reference the jwtBearer type directly. Let me know if you think I'm missing something and should convert this to an exported struct type! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems reasonable to me! I agree that ohter modules are unlikely to have a need to reference the jwtBearer type directly. |
||
jwtBearer := jwtBearer{ | ||
client: httpClient, | ||
instanceURL: instanceURL, | ||
|
@@ -78,17 +78,7 @@ func (c *jwtBearer) newAccessToken() error { | |
c.setErr(err) | ||
}() | ||
// Create JWT | ||
token := jwt.NewWithClaims( | ||
jwt.SigningMethodRS256, | ||
jwt.StandardClaims{ | ||
Issuer: c.consumerKey, | ||
Audience: c.authServerURL, | ||
Subject: c.username, | ||
ExpiresAt: time.Now().Add(c.tokenDuration).UTC().Unix(), | ||
}, | ||
) | ||
// Sign JWT with the private key | ||
signedJWT, err := token.SignedString(c.rsaPrivateKey) | ||
signedJWT, err := c.JWT() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the way this refactor worked out! 🚀 Makes sense to make this its own separate method and call it here. |
||
if err != nil { | ||
return err | ||
} | ||
|
@@ -142,6 +132,21 @@ func (c *jwtBearer) newAccessToken() error { | |
return nil | ||
} | ||
|
||
func (c *jwtBearer) JWT() (string, error) { | ||
// Create JWT | ||
token := jwt.NewWithClaims( | ||
jwt.SigningMethodRS256, | ||
jwt.StandardClaims{ | ||
Issuer: c.consumerKey, | ||
Audience: c.authServerURL, | ||
Subject: c.username, | ||
ExpiresAt: time.Now().Add(c.tokenDuration).UTC().Unix(), | ||
}, | ||
) | ||
// Sign JWT with the private key | ||
return token.SignedString(c.rsaPrivateKey) | ||
} | ||
|
||
func (c jwtBearer) checkErr() error { | ||
c.errMutex.RLock() | ||
defer c.errMutex.RUnlock() | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good comments. A couple of them felt redundant with the variable names on first look, but I think they all add a little bit information that is not in the variable name.