s4o @ master

 1package server
 2
 3import (
 4	"fmt"
 5
 6	"github.com/fasthttp/router"
 7	"github.com/valyala/fasthttp"
 8	"github.com/zitadel/oidc/pkg/client/rp"
 9)
10
11func IsAuthenticate(relayPartyProvider rp.RelyingParty, next fasthttp.RequestHandler) fasthttp.RequestHandler {
12	return func(ctx *fasthttp.RequestCtx) {
13		token := string(ctx.Request.Header.Cookie("token"))
14		tokenVerifier := relayPartyProvider.IDTokenVerifier()
15		_, err := rp.VerifyIDToken(ctx, token, tokenVerifier)
16		if err != nil {
17			ctx.Redirect("/login", 307)
18			return
19		}
20		next(ctx)
21	}
22}
23
24func NewS4OServer(clientID, clientSecret, issuer, callback, rootPath string, scopes []string) (*fasthttp.Server, error) {
25	r := router.New()
26
27	relayPartyProvider, err := rp.NewRelyingPartyOIDC(issuer, clientID, clientSecret, callback, scopes)
28	if err != nil {
29		return nil, err
30	}
31
32	fs := &fasthttp.FS{
33		Root:               rootPath,
34		IndexNames:         []string{"index.html"},
35		GenerateIndexPages: true,
36		AcceptByteRange:    true,
37		Compress:           true,
38	}
39
40	r.Handle("GET", "/login", func(ctx *fasthttp.RequestCtx) {
41		url := rp.AuthURL(" ", relayPartyProvider)
42		ctx.Redirect(url, 307)
43	})
44
45	r.Handle("GET", "/callback", func(ctx *fasthttp.RequestCtx) {
46		code := string(ctx.QueryArgs().Peek("code"))
47		token, err := rp.CodeExchange(ctx, code, relayPartyProvider)
48		if err != nil {
49			ctx.WriteString(fmt.Sprintf("Error: %+v", err))
50			return
51		}
52
53		cookie := &fasthttp.Cookie{}
54		cookie.SetKey("token")
55		cookie.SetValue(token.IDToken)
56		cookie.SetExpire(token.Expiry)
57		cookie.SetHTTPOnly(true)
58		cookie.SetSameSite(fasthttp.CookieSameSiteDefaultMode)
59		ctx.Response.Header.SetCookie(cookie)
60		ctx.Redirect("/", 307)
61	})
62
63	r.Handle("GET", "/{filepath:*}", IsAuthenticate(relayPartyProvider, fs.NewRequestHandler()))
64
65	return &fasthttp.Server{
66		Handler: r.Handler,
67	}, nil
68}