// NewToken creates new JWT token for the gien username. It embedds the given // public key as kontrolKey and signs the token with the private one. func NewToken(username, private, public string) *jwt.Token { tknID := uuid.NewV4() hostname, err := os.Hostname() if err != nil { panic(err) } if username == "" { username = "******" } if testuser := os.Getenv("TESTKEY_USERNAME"); testuser != "" { username = testuser } claims := &kitekey.KiteClaims{ StandardClaims: jwt.StandardClaims{ Issuer: "testuser", Subject: username, Audience: hostname, IssuedAt: time.Now().UTC().Unix(), Id: tknID.String(), }, KontrolKey: public, KontrolURL: "http://localhost:4000/kite", } token := jwt.NewWithClaims(jwt.GetSigningMethod("RS256"), claims) rsaPrivate, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(private)) if err != nil { panic(err) } token.Raw, err = token.SignedString(rsaPrivate) if err != nil { panic(err) } // verify the token _, err = jwt.ParseWithClaims(token.Raw, claims, func(*jwt.Token) (interface{}, error) { return jwt.ParseRSAPublicKeyFromPEM([]byte(public)) }) if err != nil { panic(err) } token.Valid = true return token }
// Verify a JWT token using an RSA public key func VerifyJWTRSA(token, publicKey string) (bool, *jwt.Token, error) { var parsedToken *jwt.Token // parse token state, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { // ensure signing method is correct if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, errors.New("unknown signing method") } parsedToken = token // verify key, err := jwt.ParseRSAPublicKeyFromPEM([]byte(publicKey)) if err != nil { return nil, err } return key, nil }) if err != nil { return false, &jwt.Token{}, err } if !state.Valid { return false, &jwt.Token{}, errors.New("invalid jwt token") } return true, parsedToken, nil }
func InitTokens() (err error) { signBytes, err := ioutil.ReadFile("config/rsaKey") if err != nil { log.Error("Error reading private key from file: ", err) return } signKey, err = jwt.ParseRSAPrivateKeyFromPEM(signBytes) if err != nil { log.Error("Error parsing private key from file: ", err) return } verifyBytes, err := ioutil.ReadFile("config/pubKey") if err != nil { log.Error("Error reading public key from file: ", err) return } verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes) if err != nil { log.Error("Error parsing public key from file: ", err) return } return }
func GetPublicKeyFromPath(path string) *rsa.PublicKey { bytes, err := ioutil.ReadFile(path) if err != nil { log.Fatal(err) } key, err := jwt.ParseRSAPublicKeyFromPEM(bytes) if err != nil { log.Fatal(err) } return key }
// ReadPublicKey is a helper function for reading an rsa.PublicKey from a PEM-encoded file // Reads public keys from both public and private key files func ReadPublicKey(file string) (*rsa.PublicKey, error) { data, err := ioutil.ReadFile(file) if err != nil { return nil, err } if privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(data); err == nil { return &privateKey.PublicKey, nil } return jwt.ParseRSAPublicKeyFromPEM(data) }
func init() { signBytes, err := ioutil.ReadFile(privKeyPath) fatal(err) signKey, err = jwt.ParseRSAPrivateKeyFromPEM(signBytes) fatal(err) verifyBytes, err := ioutil.ReadFile(pubKeyPath) fatal(err) verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes) fatal(err) }
func ParseTestPublicKey() interface{} { keyBytes, err := ioutil.ReadFile("../test_utils/public.pem") if err != nil { log.Fatal("Failed to parse public key.", err) } publicKey, err := jwt.ParseRSAPublicKeyFromPEM(keyBytes) if err != nil { log.Fatal("Failed to parse public key.", err) } return publicKey }
// 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") }
// KeyPair looks up a key pair that was used to sign Kontrol's kite key. // // The value is cached on first call of the function. func (k *Kontrol) KeyPair() (pair *KeyPair, err error) { if k.selfKeyPair != nil { return k.selfKeyPair, nil } kiteKey := k.Kite.KiteKey() if kiteKey == "" || len(k.lastPublic) == 0 { return nil, errNoSelfKeyPair } keyIndex := -1 me := new(multiError) for i := range k.lastPublic { ri := len(k.lastPublic) - i - 1 keyFn := func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, errors.New("invalid signing method") } return jwt.ParseRSAPublicKeyFromPEM([]byte(k.lastPublic[ri])) } if _, err := jwt.ParseWithClaims(kiteKey, &kitekey.KiteClaims{}, keyFn); err != nil { me.err = append(me.err, err) continue } keyIndex = ri break } if keyIndex == -1 { return nil, fmt.Errorf("no matching self key pair found: %s", me) } k.selfKeyPair = &KeyPair{ ID: k.lastIDs[keyIndex], Public: k.lastPublic[keyIndex], Private: k.lastPrivate[keyIndex], } return k.selfKeyPair, nil }
func init() { signBytes, err := ioutil.ReadFile(config.Settings.PrivKeyPath) if err != nil { logger.Log("Reading private Key File "+config.Settings.PrivKeyPath+" failed, Error: "+err.Error(), logger.ERROR) } signKey, err = jwt.ParseRSAPrivateKeyFromPEM(signBytes) if err != nil { logger.Log("Parsing private Key File failed, Error: "+err.Error(), logger.ERROR) } verifyBytes, err := ioutil.ReadFile(config.Settings.PubKeyPath) if err != nil { logger.Log("Reading public Key File "+config.Settings.PubKeyPath+" failed, Error: "+err.Error(), logger.ERROR) } verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes) if err != nil { logger.Log("Parsing public Key File failed, Error: "+err.Error(), logger.ERROR) } }
func generateKeyExtractionFunctionForJTWFlow(applicationRepo roll.ApplicationRepo) jwt.Keyfunc { return func(token *jwt.Token) (interface{}, error) { //Check the signing method if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } //The aud claim conveys the intended application the token is used to gain access to. clientID := token.Claims["aud"] if clientID == nil { return nil, errors.New("Foreign token does not include aud claim") } //Look up the application app, err := applicationRepo.SystemRetrieveApplicationByJWTFlowAudience(clientID.(string)) if err != nil { log.Info("Error looking up app for ", clientID, " ", err.Error()) return nil, err } if app == nil { log.Info("No app definition associated with audience found: ", clientID.(string)) return nil, errors.New("No app definition associated with aud found") } //We also check that the token was issued by the entity registered with the application issuer := token.Claims["iss"] if issuer == nil || issuer != app.JWTFlowIssuer { return nil, errors.New("Foreign token issuer not known") } //Grab the public key from the app definition keystring := app.JWTFlowPublicKey log.Info("validating with '", keystring, "'") //Parse the keystring return jwt.ParseRSAPublicKeyFromPEM([]byte(keystring)) } }
// 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 }
func (k *Kite) updateAuth(reg *protocol.RegisterResult) { k.configMu.Lock() defer k.configMu.Unlock() switch { case reg.KiteKey != "": k.Config.KiteKey = reg.KiteKey ex := &kitekey.Extractor{ Claims: &kitekey.KiteClaims{}, } if _, err := jwt.ParseWithClaims(reg.KiteKey, ex.Claims, ex.Extract); err != nil { k.Log.Error("auth update: unable to extract kontrol key: %s", err) break } if ex.Claims.KontrolKey != "" { reg.PublicKey = ex.Claims.KontrolKey } } // we also received a new public key (means the old one was invalidated). // Use it now. if reg.PublicKey != "" { k.Config.KontrolKey = reg.PublicKey key, err := jwt.ParseRSAPublicKeyFromPEM([]byte(reg.PublicKey)) if err != nil { k.Log.Error("auth update: unable to update kontrol key: %s", err) return } k.kontrolKey = key } }
func NewAuthResource(privateKeyPath, publicKeyPath string, tokenDuration time.Duration, validator AuthValidator) *AuthResource { verifyBytes, err := ioutil.ReadFile(publicKeyPath) fatal(err) verifyKey, err := jwt.ParseRSAPublicKeyFromPEM(verifyBytes) fatal(err) signBytes, err := ioutil.ReadFile(privateKeyPath) fatal(err) signKey, err := jwt.ParseRSAPrivateKeyFromPEM(signBytes) fatal(err) if tokenDuration < 1 { tokenDuration = DEFAULT_TOKEN_DURATION } if nil == validator { validator = DummyAuthValidator } return &AuthResource{verifyKey, signKey, tokenDuration, validator} }
func TestJWTToken(t *testing.T) { var err error var privateKeyContent, publicKeyContent []byte if privateKeyContent, err = ioutil.ReadFile("jwt-test.key"); err != nil { t.Fatal(err) } if publicKeyContent, err = ioutil.ReadFile("jwt-test.pub"); err != nil { t.Fatal(err) } if privateKey, err = jwt.ParseRSAPrivateKeyFromPEM(privateKeyContent); err != nil { t.Fatal(err) } if publicKey, err = jwt.ParseRSAPublicKeyFromPEM(publicKeyContent); err != nil { t.Fatal(err) } token := jwt.New(jwt.GetSigningMethod("RS256")) token.Claims = jwt.MapClaims{ "PERMISSION": "admin@tiedot", "exp": time.Now().Add(time.Hour * 72).Unix(), } ts, err := token.SignedString(privateKey) if err != nil { t.Fatal(err) } if token, err = jwt.Parse(ts, func(ts *jwt.Token) (interface{}, error) { return publicKey, nil }); err != nil { t.Fatal(err) } if token.Valid { t.Log(token) } else { t.Log(token) t.Fail() } }
// Callback handles the callback from the user after the identity provider provided a code to the users agent func (o *Google) Callback(w http.ResponseWriter, r *http.Request) (user map[string]string, err error) { // Delete CSRF Tokens afterwards defer func() { session, _ := o.SessionStore.Get(r, "goidc") delete(session.Values, "nonce") delete(session.Values, "state") session.Save(r, w) }() session, _ := o.SessionStore.Get(r, "goidc") oidcState, ok := session.Values["state"].(string) if !ok { return nil, fmt.Errorf("Session 'state' not found") } oidcNonce, ok := session.Values["nonce"].(string) if !ok { return nil, fmt.Errorf("Session 'nonce' not found") } err = r.ParseForm() if err != nil { return nil, fmt.Errorf("Could not parse form: %s", err) } code := r.Form.Get("code") if code == "" { return nil, fmt.Errorf("Did not receive code") } // CSRF Prevention using state if state := r.Form.Get("state"); state != oidcState { return nil, fmt.Errorf("Could not verify CSRF Token 'state': want: %s, got %s", oidcState, state) } vals := url.Values{} vals.Add("code", code) vals.Add("redirect_uri", o.RedirectURI) vals.Add("client_id", o.ClientID) vals.Add("client_secret", o.ClientSecret) vals.Add("grant_type", "authorization_code") c := http.Client{} // Exchange code for token req, err := http.NewRequest("POST", "https://www.googleapis.com/oauth2/v4/token", strings.NewReader(vals.Encode())) if err != nil { return nil, fmt.Errorf("Could not build request: %s", err) } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") resp, err := c.Do(req) if err != nil { return nil, fmt.Errorf("Error on token exchange request: %s", err) } var respValues map[string]interface{} dec := json.NewDecoder(resp.Body) err = dec.Decode(&respValues) if err != nil { return nil, fmt.Errorf("Error decoding token exchange resp to json: %s", err) } if _, ok := respValues["error"]; ok { return nil, fmt.Errorf("Error returned by the api: %v", respValues) } var idToken string idToken, _ = (respValues["id_token"]).(string) if idToken == "" { return nil, fmt.Errorf("No id token received: %#v", respValues) } // Check JWT using google certificates keyResp, err := http.Get("https://www.googleapis.com/oauth2/v1/certs") if err != nil { return nil, fmt.Errorf("Could not get keys from server: %s", err) } keyDec := json.NewDecoder(keyResp.Body) defer keyResp.Body.Close() var googleKeys map[string]string err = keyDec.Decode(&googleKeys) if err != nil { return nil, fmt.Errorf("Error decoding certificates from json: %s", err) } keylookup := func(kid string) (string, error) { for key, val := range googleKeys { if key == kid { return val, nil } } return "", fmt.Errorf("Could not find public key for kid: %s", kid) } // JWT - Verification including signing method token, err := jwt.Parse(idToken, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } kid, ok := (token.Header["kid"]).(string) if !ok { return nil, fmt.Errorf("Key id not found") } key, err := keylookup(kid) if err != nil { return nil, err } return jwt.ParseRSAPublicKeyFromPEM([]byte(key)) }) // JWT Successfull if token.Valid { // CSRF Prevention using nonce nonce, ok := (token.Claims["nonce"]).(string) if !ok { return nil, fmt.Errorf("No nonce in claims: %v", token.Claims) } if nonce != oidcNonce { return nil, fmt.Errorf("Could not verify CSRF Token 'nonce': want: %s, got %s", oidcNonce, nonce) } // Verify token audience aud, ok := (token.Claims["aud"]).(string) if !ok { return nil, fmt.Errorf("No aud in claims: %v", token.Claims) } if aud != o.ClientID { return nil, fmt.Errorf("Verification of token 'audience' failed: %v", token.Claims) } user = make(map[string]string) // Check 'sub' uid, ok := (token.Claims["sub"]).(string) if !ok { return nil, fmt.Errorf("Could not get a unique user id") } user["id"] = uid name, ok := (token.Claims["name"]).(string) if !ok { return nil, fmt.Errorf("Could not get the name of the user") } user["name"] = name return user, nil } else if ve, ok := err.(*jwt.ValidationError); ok { if ve.Errors&jwt.ValidationErrorMalformed != 0 { return nil, fmt.Errorf("ID Token is malformed") } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 { return nil, fmt.Errorf("ID Token is expired or not active yet: %s", err) } return nil, fmt.Errorf("Could not handle ID Token: %s", err) } return nil, fmt.Errorf("Could not handle ID Token: %s", err) }
UCosMSEAD909MAsyQWB4X6OJKd+V68QpFYeIx7UCgYBHgaRY6PYOBU92He36abLE MVFZBKrRMtt0s0yHgGV/SxA6wXxCMAzFdaw7IqZBbWgPiwjZET6nxLFNsLVItFIK 5h44k6mVss5xuNTdUM+i+/S8tCZW964EMkMfKHmE1XFmTuBYqY6/D4b/7hBeAFeH 3f0hQr3ZFYa5Zao4UIZKvwKBgGL8lhUBt8lENVlhEYIpLfeJfomw6AxqfAfN1GzV zpyMxX9DQqz1ZrhnvzgtwHcoqHda6/c+TgzVfBhRDw12A4f+ulvE8HupuIw4NoHS g8jc3+O5uoYuUnfbnRJyOsPtb4VSLgXz6deUmI9fugmU1l55tH93jMT4ijyzg2BJ grGxAoGAWX24Yx9qoasqEQ2rgdTsgylwL28UczKQ5KNHt2PcEfPNw6/GpfK7YmlU Heef2umEzb1K2ZK95wlMbF8zpNDWBf4PkxgfW+JEE+pO1kb5KXysBymymyXhGHAP CwH9XHqbjVlsD358AbPeKqLgTCaGo9JgsEZDBpESmBDnIPUahMc= -----END RSA PRIVATE KEY-----`)) var rsaPubKey1, _ = jwtpkg.ParseRSAPublicKeyFromPEM([]byte(`-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArZIJcPQd7aSGb80wgFpy 5SVjzzsGpfIysZ30SdWlTcWMVbATXmsDNgw98TzIeoyikSbSHEeORbKWKS2clgNs dLjYKv3XLTBaXfLcU3x9mhnk/kULN/AQgyvsRGynPris2oVzGSib7uOZK/9+u+QA KIrp7prcmMmnwvdcjFXjwzx83RTF1b+iuVGCdV0T4m1XQdm/YtIUh7JNbYrUolkd wZlOxMZuV0FDC+ms02+gyj580PylTuAD4JmtSmmijyWfEx5dsZYtGALyUxcm5Hz1 5RP3FACrv4B++BHI6smO4sWdrSYVl3sHJ60Bm6zbwuyB2twJPOdL5nVIGiIDdf+1 IwIDAQAB -----END PUBLIC KEY-----`)) var rsaKey2, _ = jwtpkg.ParseRSAPrivateKeyFromPEM([]byte(`-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA4jr/DGbPt0UDGvu6Xo2LV0F6Wf8OnyxF2IFPdG5B4X0YS3DC 9SF3clbbBivDVa2bEXppyj+eLEKlfohCWXTrJK0LxTEcneuDkF4re+BdP3q9cKRz FtI/ZVhVnD7+PS1wps7OiTM0iOaIDo9+uFrC6zBTRAiPyrdwh1ApttLdoD6i5D9D 7zzvpTXLC/UWaRz/phAaaop6dPPR1YblZEckWgqTMC3KrRX/6QJFFfpgyQzFT09W DYnmXl2gS7C2sk4UejygqmVg96JxaIaT3WiQSjxXddjR/krcA9EGNNEkpZB2W6Ux 6d63yWsNG9YJUacwI+M2q5ZW964J1s//FiNZZQIDAQABAoIBAQCoqYtU16Gs5Qq3 p0z/CVAFMY/iYMGp8fvwuhdemoULc5QVSnBPCTBgUljgdOggjFm74iPU4TEvllCD 0VqGDyDwKwNHdKH9KoTfsRWCOXfLx9pMjI4xSXZyPDU3U8+AFMyT0EMzDrXwCs8M 6/Zxw1jmtxSc+DUb0T9X4m/3GaaZvDGGShnU8/XnEh2uEHrNwWnGWYPJ/rZjNZPy
// ParsePublicKey parses a []byte representation of a public key into a rsa.PublicKey instance func ParsePublicKey(key []byte) (*rsa.PublicKey, error) { return jwt.ParseRSAPublicKeyFromPEM(key) }
// UnauthorizeCreateUpdateDeleteTest will check authorized access to Create/Update/Delete APIs func UnauthorizeCreateUpdateDeleteTest(t *testing.T, getDataFunc func(t *testing.T) []testSecureAPI, createServiceFunc func() *goa.Service, mountCtrlFunc func(service *goa.Service) error) { resource.Require(t, resource.Database) // This will be modified after merge PR for "Viper Environment configurations" publickey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(almtoken.RSAPublicKey)) if err != nil { t.Fatal("Could not parse Key ", err) } tokenTests := getDataFunc(t) for _, testObject := range tokenTests { // Build a request var req *http.Request var err error if testObject.payload == nil { req, err = http.NewRequest(testObject.method, testObject.url, nil) } else { req, err = http.NewRequest(testObject.method, testObject.url, testObject.payload) } // req, err := http.NewRequest(testObject.method, testObject.url, testObject.payload) if err != nil { t.Fatal("could not create a HTTP request") } // Add Authorization Header req.Header.Add("Authorization", testObject.jwtToken) rr := httptest.NewRecorder() service := createServiceFunc() require.NotNil(t, service) // if error is thrown during request processing, it will be caught by ErrorHandler middleware // this will put error code, status, details in recorder object. // e.g> {"id":"AL6spYb2","code":"jwt_security_error","status":401,"detail":"JWT validation failed: crypto/rsa: verification error"} //service.Use(middleware.ErrorHandler(service, true)) // e.g. > {"errors":[{"code":"unknown_error","detail":"[19v4Bp8f] 401 jwt_security_error: JWT validation failed: Token is expired","status":"401","title":"Unauthorized"}]} service.Use(jsonapi.ErrorHandler(service, true)) // append a middleware to service. Use appropriate RSA keys jwtMiddleware := goajwt.New(publickey, nil, app.NewJWTSecurity()) // Adding middleware via "app" is important // Because it will check the design and accordingly apply the middleware if mentioned in design // But if I use `service.Use(jwtMiddleware)` then middleware is applied for all the requests (without checking design) app.UseJWTMiddleware(service, jwtMiddleware) if err := mountCtrlFunc(service); err != nil { t.Fatalf("Failed to mount controller: %s", err.Error()) } // Hit the service with own request service.Mux.ServeHTTP(rr, req) require.Equal(t, testObject.expectedStatusCode, rr.Code, testObject.String()) // Below code tries to open Body response which is expected to be a JSON // If could not parse it correctly into app.JSONAPIErrors // Then it gets logged and continue the test loop //fmt.Printf("\nrr.Body = %s\n", string(rr.Body.Bytes())) jerrors := app.JSONAPIErrors{} err = json.Unmarshal(rr.Body.Bytes(), &jerrors) if err != nil { t.Log("Could not parse JSON response: ", rr.Body) // safe to continue because we alread checked rr.Code=required_value continue } // Additional checks for 'more' confirmation require.Equal(t, testObject.expectedErrorCode, *jerrors.Errors[0].Code) require.Equal(t, strconv.Itoa(testObject.expectedStatusCode), *jerrors.Errors[0].Status, testObject.String()) } }