1package jwt_test
2
3import (
4	"fmt"
5	"github.com/dgrijalva/jwt-go"
6	"time"
7)
8
9// Example (atypical) using the StandardClaims type by itself to parse a token.
10// The StandardClaims type is designed to be embedded into your custom types
11// to provide standard validation features.  You can use it alone, but there's
12// no way to retrieve other fields after parsing.
13// See the CustomClaimsType example for intended usage.
14func ExampleNewWithClaims_standardClaims() {
15	mySigningKey := []byte("AllYourBase")
16
17	// Create the Claims
18	claims := &jwt.StandardClaims{
19		ExpiresAt: 15000,
20		Issuer:    "test",
21	}
22
23	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
24	ss, err := token.SignedString(mySigningKey)
25	fmt.Printf("%v %v", ss, err)
26	//Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.QsODzZu3lUZMVdhbO76u3Jv02iYCvEHcYVUI1kOWEU0 <nil>
27}
28
29// Example creating a token using a custom claims type.  The StandardClaim is embedded
30// in the custom type to allow for easy encoding, parsing and validation of standard claims.
31func ExampleNewWithClaims_customClaimsType() {
32	mySigningKey := []byte("AllYourBase")
33
34	type MyCustomClaims struct {
35		Foo string `json:"foo"`
36		jwt.StandardClaims
37	}
38
39	// Create the Claims
40	claims := MyCustomClaims{
41		"bar",
42		jwt.StandardClaims{
43			ExpiresAt: 15000,
44			Issuer:    "test",
45		},
46	}
47
48	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
49	ss, err := token.SignedString(mySigningKey)
50	fmt.Printf("%v %v", ss, err)
51	//Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c <nil>
52}
53
54// Example creating a token using a custom claims type.  The StandardClaim is embedded
55// in the custom type to allow for easy encoding, parsing and validation of standard claims.
56func ExampleParseWithClaims_customClaimsType() {
57	tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
58
59	type MyCustomClaims struct {
60		Foo string `json:"foo"`
61		jwt.StandardClaims
62	}
63
64	// sample token is expired.  override time so it parses as valid
65	at(time.Unix(0, 0), func() {
66		token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
67			return []byte("AllYourBase"), nil
68		})
69
70		if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
71			fmt.Printf("%v %v", claims.Foo, claims.StandardClaims.ExpiresAt)
72		} else {
73			fmt.Println(err)
74		}
75	})
76
77	// Output: bar 15000
78}
79
80// Override time value for tests.  Restore default value after.
81func at(t time.Time, f func()) {
82	jwt.TimeFunc = func() time.Time {
83		return t
84	}
85	f()
86	jwt.TimeFunc = time.Now
87}
88
89// An example of parsing the error types using bitfield checks
90func ExampleParse_errorChecking() {
91	// Token from another example.  This token is expired
92	var tokenString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
93
94	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
95		return []byte("AllYourBase"), nil
96	})
97
98	if token.Valid {
99		fmt.Println("You look nice today")
100	} else if ve, ok := err.(*jwt.ValidationError); ok {
101		if ve.Errors&jwt.ValidationErrorMalformed != 0 {
102			fmt.Println("That's not even a token")
103		} else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 {
104			// Token is either expired or not active yet
105			fmt.Println("Timing is everything")
106		} else {
107			fmt.Println("Couldn't handle this token:", err)
108		}
109	} else {
110		fmt.Println("Couldn't handle this token:", err)
111	}
112
113	// Output: Timing is everything
114}
115