// Verify a token and output the claims. This is a great example // of how to verify and view a token. func verifyToken() error { // get the token tokData, err := loadData(*flagVerify) if err != nil { return fmt.Errorf("Couldn't read token: %v", err) } // trim possible whitespace from token tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{}) if *flagDebug { fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData)) } // Parse the token. Load the key from command line option token, err := jwt.Parse(string(tokData), func(t *jwt.Token) (interface{}, error) { data, err := loadData(*flagKey) if err != nil { return nil, err } if isEs() { return jwt.ParseECPublicKeyFromPEM(data) } return data, nil }) // Print some debug data if *flagDebug && token != nil { fmt.Fprintf(os.Stderr, "Header:\n%v\n", token.Header) fmt.Fprintf(os.Stderr, "Claims:\n%v\n", token.Claims) } // Print an error if we can't parse for some reason if err != nil { return fmt.Errorf("Couldn't parse token: %v", err) } // Is token invalid? if !token.Valid { return fmt.Errorf("Token is invalid") } // Print the token details if err := printJSON(token.Claims); err != nil { return fmt.Errorf("Failed to output claims: %v", err) } return nil }
// ReadPublicKeyFromPEM is a helper function for reading an rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array. // Reads public keys from both public and private key files. func ReadPublicKeyFromPEM(data []byte) (interface{}, error) { if privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(data); err == nil { return &privateKey.PublicKey, nil } if publicKey, err := jwt.ParseRSAPublicKeyFromPEM(data); err == nil { return publicKey, nil } if privateKey, err := jwt.ParseECPrivateKeyFromPEM(data); err == nil { return &privateKey.PublicKey, nil } if publicKey, err := jwt.ParseECPublicKeyFromPEM(data); err == nil { return publicKey, nil } return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA key") }
// DecodePublicKey pulls the public key out of the string passed by first // decoding from base64 and parsing the PEM encoding. func DecodePublicKey(publicKeyBase64Str string) (*ecdsa.PublicKey, error) { // Our public key has been encoded from a PEM encoded public ECDSA key into this // publicKeyBase64Str. We need to decode the base64 string in order to get the // PEM encoded certificate back out. publicKeyPEM, err := base64.StdEncoding.DecodeString(publicKeyBase64Str) if err != nil { return nil, err } // Now that we have our PEM encoded public ECDSA key, we can parse it using the // methods built into the jwt librairy into something we can use to verify the // incomming JWT's. publicKey, err := jwt.ParseECPublicKeyFromPEM(publicKeyPEM) if err != nil { return nil, err } return publicKey, nil }
// ReadPublicKeysFromPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array. // Reads public keys from both public and private key files. func ReadPublicKeysFromPEM(data []byte) ([]interface{}, error) { var block *pem.Block keys := []interface{}{} for { // read the next block block, data = pem.Decode(data) if block == nil { break } // get PEM bytes for just this block blockData := pem.EncodeToMemory(block) if privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(blockData); err == nil { keys = append(keys, &privateKey.PublicKey) continue } if publicKey, err := jwt.ParseRSAPublicKeyFromPEM(blockData); err == nil { keys = append(keys, publicKey) continue } if privateKey, err := jwt.ParseECPrivateKeyFromPEM(blockData); err == nil { keys = append(keys, &privateKey.PublicKey) continue } if publicKey, err := jwt.ParseECPublicKeyFromPEM(blockData); err == nil { keys = append(keys, publicKey) continue } // tolerate non-key PEM blocks for backwards compatibility // originally, only the first PEM block was parsed and expected to be a key block } if len(keys) == 0 { return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA key") } return keys, nil }