mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Switch to jwks instead of custom /info
This commit is contained in:
parent
068b19c936
commit
6391a99bb9
@ -1,20 +1,14 @@
|
||||
import jwt from "@elysiajs/jwt";
|
||||
import Elysia, { t } from "elysia";
|
||||
import { createRemoteJWKSet } from "jose";
|
||||
|
||||
export let jwtSecret = process.env.JWT_SECRET!;
|
||||
if (!jwtSecret) {
|
||||
const auth = process.env.AUTH_SERVER ?? "http://auth:4568/auth";
|
||||
try {
|
||||
const ret = await fetch(`${auth}/info`);
|
||||
const info = await ret.json();
|
||||
jwtSecret = info.publicKey;
|
||||
} catch (error) {
|
||||
console.error(`Can't access auth server at ${auth}:\n${error}`);
|
||||
}
|
||||
}
|
||||
const jwtSecret = process.env.JWT_SECRET;
|
||||
const jwks = createRemoteJWKSet(
|
||||
new URL(process.env.AUTH_SERVER ?? "http://auth:4568"),
|
||||
);
|
||||
|
||||
export const auth = new Elysia({ name: "auth" })
|
||||
.use(jwt({ secret: jwtSecret }))
|
||||
.use(jwt({ secret: jwtSecret ?? jwks }))
|
||||
.guard({
|
||||
headers: t.Object({
|
||||
authorization: t.String({ pattern: "^Bearer .+$" }),
|
||||
@ -25,7 +19,7 @@ export const auth = new Elysia({ name: "auth" })
|
||||
return {
|
||||
beforeHandle: () => {},
|
||||
resolve: async ({ headers: { authorization }, jwt }) => {
|
||||
console.log(authorization.slice(7));
|
||||
console.log(authorization?.slice(7));
|
||||
const user = await jwt.verify(authorization?.slice(7));
|
||||
console.log("macro", user);
|
||||
return { user };
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { swagger } from "@elysiajs/swagger";
|
||||
import { jwtSecret } from "./auth";
|
||||
import { app } from "./base";
|
||||
import { processImages } from "./controllers/seed/images";
|
||||
import { migrate } from "./db";
|
||||
@ -7,11 +6,6 @@ import { comment } from "./utils";
|
||||
|
||||
await migrate();
|
||||
|
||||
if (!jwtSecret) {
|
||||
console.error("Missing jwt secret or auth server. exiting");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// run image processor task in background
|
||||
processImages();
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
# http route prefix (will listen to $KEIBI_PREFIX/users for example)
|
||||
KEIBI_PREFIX=""
|
||||
|
||||
# The url you can use to reach your kyoo instance. This is used during oidc to redirect users to your instance.
|
||||
PUBLIC_URL=http://localhost:8901
|
||||
|
||||
# Database things
|
||||
POSTGRES_USER=kyoo
|
||||
POSTGRES_PASSWORD=password
|
||||
|
@ -17,13 +17,12 @@ type Configuration struct {
|
||||
Prefix string
|
||||
JwtPrivateKey *rsa.PrivateKey
|
||||
JwtPublicKey *rsa.PublicKey
|
||||
Issuer string
|
||||
PublicUrl string
|
||||
DefaultClaims jwt.MapClaims
|
||||
ExpirationDelay time.Duration
|
||||
}
|
||||
|
||||
var DefaultConfig = Configuration{
|
||||
Issuer: "kyoo",
|
||||
DefaultClaims: make(jwt.MapClaims),
|
||||
ExpirationDelay: 30 * 24 * time.Hour,
|
||||
}
|
||||
@ -54,6 +53,7 @@ func LoadConfiguration(db *dbc.Queries) (*Configuration, error) {
|
||||
}
|
||||
}
|
||||
|
||||
ret.PublicUrl = os.Getenv("PUBLIC_URL")
|
||||
ret.Prefix = os.Getenv("KEIBI_PREFIX")
|
||||
|
||||
if ret.JwtPrivateKey == nil {
|
||||
|
13
auth/go.mod
13
auth/go.mod
@ -16,7 +16,18 @@ require (
|
||||
github.com/swaggo/swag v1.16.4
|
||||
)
|
||||
|
||||
require github.com/otaxhu/type-mismatch-encoding v0.0.0-20241118152201-1861af90dd01 // indirect
|
||||
require (
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/jwx v1.2.30 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/otaxhu/type-mismatch-encoding v0.0.0-20241118152201-1861af90dd01 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
|
19
auth/go.sum
19
auth/go.sum
@ -9,6 +9,8 @@ github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6Ct
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/dhui/dktest v0.4.3 h1:wquqUxAFdcUgabAVLvSCOKOlag5cIZuaOjYIBOWdsR0=
|
||||
github.com/dhui/dktest v0.4.3/go.mod h1:zNK8IwktWzQRm6I/l2Wjp7MakiyaFWv4G1hjmodmMTs=
|
||||
github.com/dhui/dktest v0.4.4 h1:+I4s6JRE1yGuqflzwqG+aIaMdgXIorCf5P98JnaAWa8=
|
||||
@ -54,6 +56,8 @@ github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL
|
||||
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
|
||||
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
@ -99,6 +103,19 @@ github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
||||
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
||||
github.com/lestrrat-go/jwx v1.2.30 h1:VKIFrmjYn0z2J51iLPadqoHIVLzvWNa1kCsTqNDHYPA=
|
||||
github.com/lestrrat-go/jwx v1.2.30/go.mod h1:vMxrwFhunGZ3qddmfmEm2+uced8MSI6QFWGTKygjSzQ=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
@ -134,7 +151,9 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/swaggo/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk=
|
||||
|
44
auth/jwt.go
44
auth/jwt.go
@ -2,8 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net/http"
|
||||
@ -12,6 +10,7 @@ import (
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/lestrrat-go/jwx/jwk"
|
||||
)
|
||||
|
||||
type Jwt struct {
|
||||
@ -19,11 +18,6 @@ type Jwt struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
// The public key used to sign jwt tokens. It can be used by your services to check if the jwt is valid.
|
||||
PublicKey string `json:"publicKey"`
|
||||
}
|
||||
|
||||
// @Summary Get JWT
|
||||
// @Description Convert a session token to a short lived JWT.
|
||||
// @Tags jwt
|
||||
@ -56,13 +50,13 @@ func (h *Handler) CreateJwt(c echo.Context) error {
|
||||
claims := maps.Clone(session.User.Claims)
|
||||
claims["sub"] = session.User.Id.String()
|
||||
claims["sid"] = session.Id.String()
|
||||
claims["iss"] = h.config.Issuer
|
||||
claims["iss"] = h.config.PublicUrl
|
||||
claims["iat"] = &jwt.NumericDate{
|
||||
Time: time.Now().UTC(),
|
||||
}
|
||||
claims["exp"] = &jwt.NumericDate{
|
||||
Time: time.Now().UTC().Add(time.Hour),
|
||||
}
|
||||
claims["iss"] = &jwt.NumericDate{
|
||||
Time: time.Now().UTC(),
|
||||
}
|
||||
jwt := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
|
||||
t, err := jwt.SignedString(h.config.JwtPrivateKey)
|
||||
if err != nil {
|
||||
@ -74,21 +68,21 @@ func (h *Handler) CreateJwt(c echo.Context) error {
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary Info
|
||||
// @Description Get info like the public key used to sign the jwts.
|
||||
// @Summary Jwks
|
||||
// @Description Get the jwks info, used to validate jwts.
|
||||
// @Tags jwt
|
||||
// @Produce json
|
||||
// @Success 200 {object} Info
|
||||
// @Router /info [get]
|
||||
// @Success 200 {object} jwk.Key
|
||||
// @Router /.well-known/jwks.json [get]
|
||||
func (h *Handler) GetInfo(c echo.Context) error {
|
||||
key := pem.EncodeToMemory(
|
||||
&pem.Block{
|
||||
Type: "RSA PUBLIC KEY",
|
||||
Bytes: x509.MarshalPKCS1PublicKey(h.config.JwtPublicKey),
|
||||
},
|
||||
)
|
||||
|
||||
return c.JSON(200, Info{
|
||||
PublicKey: string(key),
|
||||
})
|
||||
key, err := jwk.New(h.config.JwtPublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key.Set("use", "sig")
|
||||
key.Set("key_ops", "verify")
|
||||
set := jwk.NewSet()
|
||||
set.Add(key)
|
||||
return c.JSON(200, set)
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ func main() {
|
||||
r.DELETE("/sessions/:id", h.Logout)
|
||||
|
||||
g.GET("/jwt", h.CreateJwt)
|
||||
g.GET("/info", h.GetInfo)
|
||||
e.GET("/.well-known/jwks.json", h.GetInfo)
|
||||
|
||||
g.GET("/swagger/*", echoSwagger.WrapHandler)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user