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}