Support for Placeholder Integration on JWKURL#96
Conversation
go.mod
Outdated
| @@ -1,4 +1,4 @@ | |||
| module github.com/ggicci/caddy-jwt | |||
| module github.com/Cafeine42/caddy-jwt | |||
There was a problem hiding this comment.
Got it. You don't have to change the module path if you do this in Git:
# clone the repo
git clone git@github.com:ggicci/httpin.git
# rename origin to upstream
git remote rename origin upstream
# add your forked repo as the origin remote
git remote add origin git@github.com:Cafeine42/httpin.git
# make some changes to the source code and commit to origin (your own repo) and open PR on GitHub
git add ...
git commit ...
git push origin ...
There was a problem hiding this comment.
I have this error when i try to install my version, it's why i changed this line.
RUN apk add --no-cache git &&
xcaddy build
--output /usr/local/bin/frankenphp
...
# Auth module
--with github.com/Cafeine42/caddy-jwt@v0.0.10
11.73 2025/05/27 09:45:51 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -v -ldflags -w -s -extldflags '-Wl,-z,stack-size=0x80000' github.com/Cafeine42/caddy-jwt@v0.0.9 github.com/caddyserver/caddy/v2
15.89 go: downloading github.com/Cafeine42/caddy-jwt v0.0.9
21.22 go: github.com/Cafeine42/caddy-jwt@v0.0.9 found: parsing go.mod:
21.22 module declares its path as: github.com/ggicci/caddy-jwt
21.22 but was required as: github.com/Cafeine42/caddy-jwt
21.22 go: github.com/Cafeine42/caddy-jwt@v0.0.9 requires github.com/Cafeine42/caddy-jwt@v0.0.9: parsing go.mod:
21.22 module declares its path as: github.com/ggicci/caddy-jwt
21.22 but was required as: github.com/Cafeine42/caddy-jwt
21.22 2025/05/27 09:46:00 [FATAL] exit status 1
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #96 +/- ##
==========================================
- Coverage 95.10% 90.09% -5.01%
==========================================
Files 2 2
Lines 347 404 +57
==========================================
+ Hits 330 364 +34
- Misses 12 28 +16
- Partials 5 12 +7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Thank you @Cafeine42 very much for the contribution! I will take a look this weekend and aim to merge and release as well. |
jwt.go
Outdated
| jwkCache *jwk.Cache | ||
| jwkCachedSet jwk.Set | ||
| // JWK cache by resolved URL to support placeholders in JWKURL | ||
| jwkCaches map[string]*struct { |
There was a problem hiding this comment.
Since the keys are populated during requests handling, I believe it should be guarded with a sync.RWMutex to allow concurrent access safely. No?
jwt.go
Outdated
| } | ||
|
|
||
| func (ja *JWTAuth) setupJWKLoader() { | ||
| // Initialiser le cache pour toutes les URL possibles |
There was a problem hiding this comment.
Cool, French is beautiful, but let's use English here 😆
jwt.go
Outdated
| cache *jwk.Cache | ||
| cachedSet jwk.Set | ||
| }) | ||
| ja.logger.Info("JWK cache initialized for placeholder URL", zap.String("placeholder_url", ja.JWKURL)) |
There was a problem hiding this comment.
Does it have to be a placeholder URL here? Looks like the wording is a little misleading as both a static JWK URL and a placeholder URL will go this code path.
jwt.go
Outdated
| // Resolve JWKURL with placeholders | ||
| replacer := request.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) | ||
| resolvedURL := replacer.ReplaceAll(ja.JWKURL, "") | ||
|
|
There was a problem hiding this comment.
Even there're only two lines of code here, I would prefer creating a separate function to get the JWK URL which is bound to the given HTTP request.
jwt.go
Outdated
| ja.logger.Info("JWK unresolved", zap.String("placeholder_url", ja.JWKURL)) | ||
| ja.logger.Info("JWK resolved", zap.String("placeholder_url", resolvedURL)) |
There was a problem hiding this comment.
Maybe it's better to merge them as one.
| // Replace placeholders in the signKey such as {file./path/to/sign_key.txt} | ||
| signKey = repl.ReplaceAll(signKey, "") | ||
| if len(signKey) == 0 { | ||
| resolvedSignKey := repl.ReplaceAll(signKey, "") |
jwt.go
Outdated
| cache *jwk.Cache | ||
| cachedSet jwk.Set |
There was a problem hiding this comment.
Also, shall we create a struct type for the caches? I saw it has been used multiple times in the code later.
type jwkCacheEntry struct {
URL String
Cache *jwk.Cache
CachedSet jwk.Set
}
jwt.go
Outdated
| cache *jwk.Cache | ||
| cachedSet jwk.Set |
There was a problem hiding this comment.
Please simplify this by using a new type, which was requested in my comments above.
| // Try to refresh the cache immediately | ||
| _, err = cache.Refresh(context.Background(), resolvedURL) | ||
| if err != nil { | ||
| ja.logger.Warn("failed to refresh JWK cache during initialization", zap.Error(err), zap.String("url", resolvedURL)) | ||
| // Continue even in case of error, the important thing is that the URL is registered | ||
| } |
There was a problem hiding this comment.
This block is a repeat of refreshJWKCache(resolvedURL). I can imagine why you didn't call refreshJWKCache here was that it creates recusive calls.
Creating fine grained functions can avoid this. For example:
refreshJWKCache(entry, resolvedURL)
// or even better when we have the new type for the entry
entry.refresh() // entry: of jwkCacheEntry
jwt.go
Outdated
| entry, err := ja.getOrCreateJWKCache(resolvedURL) | ||
| if err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
Since we want to reuse the refresh logic in getOrCreateJWKCache(), let's don't call getOrCreateJWKCache() here. The function should have less dependencies. I would suggest encapsulating it in a method of the proposed jwkCacheEntry struct above.
ggicci
left a comment
There was a problem hiding this comment.
hey @Cafeine42, thanks for the contribution. The code logic looks good to me. I left a bunch of comments there, basically all for code simplifying. Please let me know if you want my help on the update in case you don't have much time.
de67265 to
03b05a6
Compare
|
@ggicci Thanks for the review ! I’ve implemented the suggested changes, they help simplify the code. I wasn’t able to test everything thoroughly on my project though, so let me know if you run into any issues or if there’s anything else to tweak. I might test it more extensively next week. |
|
Too late now, I will merge and add docs and then do the release soon. Again, thanks very much for the feature implementation :) |
For #95
Exemple of use case in Caddyfile :