Skip to content

Commit 587cc98

Browse files
committed
Merge remote-tracking branch 'origin/master'
# Conflicts: # go.mod # go.sum
2 parents 2e1fba0 + 4dd563b commit 587cc98

File tree

10 files changed

+396
-87
lines changed

10 files changed

+396
-87
lines changed

example/main.go

+170-49
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,63 @@ import (
66
"github.com/ProtocolONE/authone-jwt-verifier-golang"
77
"github.com/ProtocolONE/authone-jwt-verifier-golang/example/nocache"
88
jwt_middleware "github.com/ProtocolONE/authone-jwt-verifier-golang/middleware/echo"
9-
"github.com/labstack/echo"
10-
"github.com/labstack/echo/middleware"
9+
"github.com/labstack/echo/v4"
10+
"github.com/labstack/echo/v4/middleware"
1111
"github.com/labstack/gommon/log"
12+
"html/template"
13+
"io"
1214
"net/http"
15+
"time"
1316
)
1417

1518
var (
16-
clientID = "5c77953f51c0950001436152"
17-
clientSecret = "tGtL8HcRDY5X7VxEhyIye2EhiN9YyTJ5Ny0AndLNXQFgKCSgUKE0Ti4X9fHK6Qib"
18-
scopes = []string{"openid", "offline"}
19-
responseType = "code"
20-
redirectURL = "http://127.0.0.1:1323/auth/callback"
21-
authDomain = "https://auth1.tst.protocol.one"
22-
jwtv *jwtverifier.JwtVerifier
19+
//clientID = "5c7fd8c50dd75d000162c69f"
20+
clientID = "5c935c8e02429c5c98920f2c"
21+
//clientSecret = "TVzu97mMqsn4bRQbgS07MdIuf3TMgZHEm0fjKWWP5DvzppyTtXA8sgQtqazr91zq"
22+
clientSecret = "BxupC6l655Y3gnFQxfxME4IvLvDpKYwbfRp9ri07zxnPzFaLraCgvLkrzh0618Rt"
23+
scopes = []string{"openid", "offline"}
24+
redirectURL = "http://localhost:1323/auth/callback"
25+
logoutRedirectUri = "http://127.0.0.1:1323/logout_result"
26+
authDomain = "http://127.0.0.1:8080"
27+
jwtv *jwtverifier.JwtVerifier
2328
)
2429

30+
type payload struct {
31+
ClientID string `json:"client_id"`
32+
Result bool `json:"result"`
33+
Error string `json:"error"`
34+
AccessToken string `json:"access_token"`
35+
RefreshToken string `json:"refresh_token"`
36+
Expire time.Time `json:"expire"`
37+
IntrospectAccessToken jwtverifier.IntrospectToken `json:"introspect_access_token"`
38+
IntrospectRefreshToken jwtverifier.IntrospectToken `json:"introspect_refresh_token"`
39+
UserInfo jwtverifier.UserInfo `json:"user_info"`
40+
IdToken jwtverifier.IdToken `json:"id_token"`
41+
}
42+
43+
type Object struct {
44+
Identifier string
45+
}
46+
47+
type Template struct {
48+
templates *template.Template
49+
}
50+
51+
var (
52+
authCookieName = "auth1_access_token"
53+
obj = &Object{}
54+
)
55+
56+
func (t *Template) Render(w io.Writer, name string, data interface{}, ctx echo.Context) error {
57+
return t.templates.ExecuteTemplate(w, name, data)
58+
}
59+
2560
func main() {
61+
t := &Template{
62+
templates: template.Must(template.ParseGlob("templates/*.html")),
63+
}
2664
e := echo.New()
65+
e.Renderer = t
2766
e.Logger.SetLevel(log.ERROR)
2867
e.Use(middleware.Logger())
2968
e.Use(nocache.NoCache())
@@ -37,23 +76,52 @@ func main() {
3776
}
3877
jwtv = jwtverifier.NewJwtVerifier(settings)
3978

40-
// Routes
79+
f := func(ui *jwtverifier.UserInfo) {
80+
obj.Identifier = string(ui.UserID)
81+
}
82+
83+
// Main page with login|logout actions
4184
e.GET("/", index)
4285
// Create state and redirect to auth endpoint
4386
e.GET("/authme", authMeProcess)
4487
// Validate auth code result
4588
e.GET("/auth/callback", authCallback)
46-
// Validate auth header
89+
// Check access to page by authentication header
4790
e.GET("/private", privateZone, jwt_middleware.AuthOneJwtWithConfig(jwtv))
48-
// Routes
91+
// Check access to page by authentication header with custom callable function
92+
e.GET("/private_callable", privateZoneCallable, jwt_middleware.AuthOneJwtCallableWithConfig(jwtv, f))
93+
// Page without authentication header validation
4994
e.GET("/some-route", someRoute)
95+
// Logout
96+
e.GET("/logout", logout)
97+
// Logout callback for clean local tokens, session and etc.
98+
e.GET("/logout_result", logoutResult)
5099

51100
// Start server
52101
e.Logger.Fatal(e.Start(":1323"))
53102
}
54103

55104
func index(c echo.Context) error {
56-
return c.HTML(http.StatusOK, "<a href=\"/authme\">Auth me</a>")
105+
cookie, _ := c.Request().Cookie(authCookieName)
106+
isAuthenticate := cookie.String() != ""
107+
108+
if isAuthenticate == true {
109+
userInfo, err := userinfo(c.Request().Context(), cookie.Value)
110+
if err != nil {
111+
c.Echo().Logger.Error("Unable to get user info")
112+
fmt.Print(err)
113+
} else {
114+
fmt.Print(userInfo)
115+
}
116+
}
117+
118+
return c.Render(http.StatusOK, "index.html", map[string]interface{}{
119+
"AuthDomain": authDomain,
120+
"ClientID": clientID,
121+
"RedirectUri": redirectURL,
122+
"LogoutRedirectUri": logoutRedirectUri,
123+
"IsAuthenticate": isAuthenticate,
124+
})
57125
}
58126

59127
func someRoute(c echo.Context) error {
@@ -66,75 +134,128 @@ func privateZone(c echo.Context) error {
66134
return c.HTML(http.StatusOK, "")
67135
}
68136

137+
func privateZoneCallable(c echo.Context) error {
138+
fmt.Printf("User: %+v\n", obj.Identifier)
139+
return c.HTML(http.StatusOK, "")
140+
}
141+
69142
func authMeProcess(c echo.Context) error {
70143
options := jwtverifier.AuthUrlOption{
71-
Key: "state",
72-
Value: "example_state_string",
144+
Key: "test1",
145+
Value: "value1",
73146
}
74-
url := jwtv.CreateAuthUrl(responseType, options)
75-
fmt.Printf("%s\n", url)
76-
return c.Redirect(http.StatusPermanentRedirect, url)
147+
u := jwtv.CreateAuthUrl("example_state_string", options)
148+
return c.Redirect(http.StatusPermanentRedirect, u)
149+
}
150+
151+
func logout(c echo.Context) error {
152+
c.SetCookie(&http.Cookie{Name: authCookieName, Value: "", Path: "/", Expires: time.Unix(0, 0)})
153+
url := fmt.Sprintf("%s://%s", c.Scheme(), c.Request().Host)
154+
return c.Redirect(http.StatusPermanentRedirect, jwtv.CreateLogoutUrl(url))
155+
}
156+
157+
func logoutResult(c echo.Context) error {
158+
c.SetCookie(&http.Cookie{Name: authCookieName, Value: "", Path: "/", Expires: time.Unix(0, 0)})
159+
return c.Render(http.StatusOK, "logout.html", map[string]interface{}{})
77160
}
78161

79162
func authCallback(c echo.Context) error {
163+
payload := &payload{ClientID: clientID, Result: true}
80164
ctx := c.Request().Context()
81165
t, err := jwtv.Exchange(ctx, fmt.Sprint(c.QueryParam("code")))
82166
if err != nil {
83167
c.Echo().Logger.Error("Unable to get auth token")
84-
return c.HTML(http.StatusBadRequest, "Authorization error")
85-
}
86-
fmt.Printf("AccessToken: %+v\n", t.AccessToken)
168+
payload.Error = fmt.Sprintf("Authorization error: %s\n", err.Error())
169+
} else {
170+
c.SetCookie(&http.Cookie{Name: authCookieName, Value: t.AccessToken, Path: "/", Expires: t.Expiry})
87171

88-
if err := introspect(ctx, t); err != nil {
89-
c.Echo().Logger.Error("Unable to get introspect access token")
90-
fmt.Print(err)
91-
return nil
92-
}
172+
payload.AccessToken = t.AccessToken
173+
payload.RefreshToken = t.RefreshToken
174+
payload.Expire = t.Expiry
175+
fmt.Printf("AccessToken string: %s\n", t.AccessToken)
176+
fmt.Printf("RefreshToken string: %s\n", t.RefreshToken)
177+
fmt.Printf("Token expire: %s", t.Expiry)
178+
179+
introspectAccessToken, introspectRefreshToken, err := introspect(ctx, t)
180+
if err != nil {
181+
c.Echo().Logger.Error("Unable to get introspect access token")
182+
fmt.Print(err)
183+
payload.Error = fmt.Sprintf("Unable to introspect token: %s\n", err.Error())
184+
} else {
185+
payload.IntrospectAccessToken = *introspectAccessToken
186+
payload.IntrospectRefreshToken = *introspectRefreshToken
187+
}
188+
189+
userInfo, err := userinfo(ctx, t.AccessToken)
190+
if err != nil {
191+
c.Echo().Logger.Error("Unable to get user info")
192+
fmt.Print(err)
193+
payload.Error = fmt.Sprintf("Unable to get user info: %s\n", err.Error())
194+
} else {
195+
payload.UserInfo = *userInfo
196+
}
93197

94-
if err := userinfo(ctx, t); err != nil {
95-
c.Echo().Logger.Error("Unable to get user info")
96-
fmt.Print(err)
97-
return nil
198+
idToken, err := validateIdToken(ctx, t)
199+
if err != nil {
200+
c.Echo().Logger.Error("Unable to get validate id token")
201+
fmt.Print(err)
202+
payload.Error = fmt.Sprintf("Unable to validate id token: %s\n", err.Error())
203+
} else {
204+
payload.IdToken = *idToken
205+
}
98206
}
99207

100-
if err := validateIdToken(ctx, t); err != nil {
101-
c.Echo().Logger.Error("Unable to get validate id token")
102-
fmt.Print(err)
103-
return nil
208+
if payload.Error != "" {
209+
payload.Result = false
104210
}
105211

106-
return nil
212+
return c.Render(http.StatusOK, "callback.html", map[string]interface{}{
213+
"Result": payload.Result,
214+
"Error": payload.Error,
215+
"AccessToken": payload.AccessToken,
216+
"RefreshToken": payload.RefreshToken,
217+
"Expire": payload.Expire,
218+
})
107219
}
108220

109-
func introspect(c context.Context, token *jwtverifier.Token) error {
110-
t, err := jwtv.Introspect(c, token.AccessToken)
221+
func introspect(c context.Context, token *jwtverifier.Token) (*jwtverifier.IntrospectToken, *jwtverifier.IntrospectToken, error) {
222+
at, err := jwtv.Introspect(c, token.AccessToken)
111223
if err != nil {
112-
return err
224+
return nil, nil, err
113225
}
114-
fmt.Printf("JWT token: %+v\n", t)
115-
fmt.Printf("Expiry: %+v\n", token.Expiry)
116-
return nil
226+
fmt.Printf("AccessToken JWT: %+v\n", at)
227+
fmt.Printf("AccessToken expiry: %+v\n", at.Exp)
228+
229+
rt, err := jwtv.Introspect(c, token.RefreshToken)
230+
if err != nil {
231+
return nil, nil, err
232+
}
233+
fmt.Printf("RefreshToken JWT: %+v\n", rt)
234+
fmt.Printf("RefreshToken expiry: %+v\n", rt.Exp)
235+
236+
return at, rt, nil
117237
}
118238

119-
func userinfo(c context.Context, token *jwtverifier.Token) error {
120-
info, err := jwtv.GetUserInfo(c, token.AccessToken)
239+
func userinfo(c context.Context, token string) (*jwtverifier.UserInfo, error) {
240+
info, err := jwtv.GetUserInfo(c, token)
121241
if err != nil {
122-
return err
242+
return nil, err
123243
}
124244
fmt.Printf("User info: %+v\n", info)
125-
return nil
245+
return info, nil
126246
}
127247

128-
func validateIdToken(c context.Context, token *jwtverifier.Token) error {
248+
func validateIdToken(c context.Context, token *jwtverifier.Token) (*jwtverifier.IdToken, error) {
129249
id := token.Extra("id_token")
130250
if id == nil {
131251
fmt.Print("ID token is not required\n")
132-
return nil
252+
return nil, nil
133253
}
254+
fmt.Printf("ID token string: %+v\n", id)
134255
t, err := jwtv.ValidateIdToken(c, fmt.Sprint(id))
135256
if err != nil {
136-
return err
257+
return nil, err
137258
}
138259
fmt.Printf("ID token: %+v\n", t)
139-
return nil
260+
return t, nil
140261
}

example/nocache/nocache.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ package nocache
55
import (
66
"time"
77

8-
"github.com/labstack/echo"
9-
emw "github.com/labstack/echo/middleware"
8+
"github.com/labstack/echo/v4"
9+
emw "github.com/labstack/echo/v4/middleware"
1010
)
1111

1212
type (

example/templates/callback.html

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8"/>
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
6+
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
7+
</head>
8+
<body>
9+
<h1>{{index . "Result"}}</h1>
10+
<script>
11+
window.AUTH_API_URL = "{{index . "AuthDomain"}}";
12+
window.AUTH_CALLBACK = {
13+
result: "{{index . "Result"}}",
14+
error: "{{index . "Error"}}",
15+
access_token: "{{index . "AccessToken"}}",
16+
refresh_token: "{{index . "RefreshToken"}}",
17+
expire: "{{index . "Expire"}}",
18+
};
19+
</script>
20+
<script src="https://static.protocol.one/auth/form/dev/auth-web-form.js"></script>
21+
</body>
22+
</html>

0 commit comments

Comments
 (0)