zitadel / oidc Goto Github PK
View Code? Open in Web Editor NEWEasy to use OpenID Connect client and server library written for Go and certified by the OpenID Foundation
Home Page: https://zitadel.com
License: Apache License 2.0
Easy to use OpenID Connect client and server library written for Go and certified by the OpenID Foundation
Home Page: https://zitadel.com
License: Apache License 2.0
Is your feature request related to a problem? Please describe.
After the user logs in, call back /authorize/callback?id=。 At this time, the ID is authrequestid. I can't know the logged in user ID. Therefore, the relationship between the logged in user ID and authrequestid needs to be implemented by yourself. This may be a problem
Describe the solution you'd like
In / authorize / callback? Id = add a parameter to the interface, such as / authorize / callback? Id = & uid =, where uid is the currently logged in user ID.
At the same time, the interface authrequestbyid (context. Context, string) (authrequest, error) adds the parameter authrequestbyid (context. Context, ID, uid, string) (authrequest, error)
As a developer I want to be able to use the device authorization grant for authentication, to be able to authenticate my devices.
Acceptance Criteria
Additional Context
Reported issue: #141
Is your feature request related to a problem? Please describe.
Using the client example app
with auth0 and profile
scope leads to this error:
failed to exchange token: json: cannot unmarshal string into Go struct field .updated_at of type int64
Describe the solution you'd like
Like for aws incognito in this issue, zitadel/oidc
could be able to parse also non-compliant fields used in the wild.
Auth0 uses RCF3339. Example of field:
"updated_at": "2021-05-11T21:13:25.566Z"
Describe alternatives you've considered
Removing the profile
scope is a workaround.
Additional context
I marked this as a feature since it is a non-complaint implementation of auth0 and not a bug on zitadel/oidc
Related to #137
The library should be able to handle multiple issuers on a single OpenID Provider.
Acceptance Criteria
Is your feature request related to a problem? Please describe.
I'm trying to use the library not only for the first login but also to keep the access token in a cookie and then verify it on every request. However it seems there are only methods to verify the id token (which I don't need) and not the access token give a provider.
Describe the solution you'd like
Have a function that given an access token, validates it against the provider keys
Describe alternatives you've considered
Use the jwt package to verify it but the signing keys are private variables on the oauth config
In the example/client/api
i always get 401 from token instrospection when calling /protected.
resp, err := rs.Introspect(r.Context(), provider, token)
if err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}
The step:
example/client/service
Did i miss something?
Is your feature request related to a problem? Please describe.
Trying to set a prompt value in authorization request
Describe the solution you'd like
Allow WithPrompt to be included in the URL produced by AuthURL() inside rp.AuthURLHandler()
Describe alternatives you've considered
New to the language but couldn't see an obvious way to inject the prompt AuthURLOpt into the authorization request
Additional context
None.
Describe the bug
When user info is missing address field it's decoded into userinfo
struct where Address
field has UserInfoAddress
type but nil
value.
UserInfoAddress
type doesn't expect nil
as receiver, so code like info.GetAddress().GetCountry()
panics.
To Reproduce
Steps to reproduce the behavior:
info.GetAddress().GetCountry()
Expected behavior
Probably, returning default values for all fields (e.g. ""
).
Another (IMO better but breaking) way is to return a pointer. So it will be possible to check value GetAddress() == nil
Additional context
Temp workaround:
func isNil(val any) bool {
return val == nil || (reflect.ValueOf(val).Kind() == reflect.Ptr && reflect.ValueOf(val).IsNil())
}
addr := info.GetAddress()
if !isNil(addr) {
// ...
}
I built an OpenID provider that works from within an inetd-like scenario: the provider interacts with stdin and stdout, and it expects its parent process to create a socket before connecting this socket to the child's (i.e., the provider's) stdin and stdout. This seems to expose a concurrency bug in NewOpenIDProvider()
. The symptom of this is an "unsupported signing algorithm" error later in the code.
NewOpenIDProvider() contains the statement go storage.GetSigningKey(ctx, keyCh)
, but it seems to perform no synchronization that would ensure the value is updated before it is later used. I think my use caused the oidc engine to rely on the signing key before this Go routine set it by way of keyCh
.
I worked around this by adding a runtime.Gosched()
immediately after my provider calls NewOpenIDProvider()
. This seems to fix things in my odd case.
Is your feature request related to a problem? Please describe.
The current definition of OAuth 2.1 expects a client secret when a confidential app is used in combination with PKCE.
Describe the solution you'd like
Check of client secret if PKCE flow is used when app is typed as confidential.
Describe alternatives you've considered
Split of compliance with a different version, to bet at least different from the new version of OAuth.
Additional context
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-09#authorization_codes
Is your feature request related to a problem? Please describe.
The following code is awkward as I need to guess that the structure that GetClaim()
returns is map[string]string
.
val, ok := introspectionResponse.GetClaim("cnf").(map[string]string)
if !ok {
http.Error(rw, "", http.StatusUnauthorized)
return
}
expectedClientCertificateHash, err := base64.URLEncoding.DecodeString(val["x5t#S256"])
if err != nil {
http.Error(rw, "", http.StatusUnauthorized)
return
}
if !bytes.Equal(clientCertificateHash[:], expectedClientCertificateHash) {
http.Error(rw, "", http.StatusUnauthorized)
return
}
Describe the solution you'd like
I'd prefer GetClaim()
to take an output parameter instead. so that I can marshal safely to my own struct type:
func (r IntrospectionResponse) GetClaim(key string, out interface{}) error {...}
type ConfirmationClaim struct {
CertificateThumbprint string `json:"x5t#S256"`
}
var cnf ConfirmationClaim
err := introspectionResponse.GetClaim("cnf", &cnf)
if err != nil { ... }
expectedClientCertificateHash, err := base64.URLEncoding.DecodeString(cnf.CertificateThumbprint)
if err != nil { ... }
if !bytes.Equal(clientCertificateHash[:], cnf.CertificateThumbprint {
http.Error(rw, "", http.StatusUnauthorized)
return
}
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
We have client key stored in a database as a string. We want to pass it as an option when create an RP instance. However, there is only one option - WithClientKey
. It accepts path to file. So we have to store key data to the fs and then pass a path to the temporary file.
There is already a function ConfigFromKeyFileData
, we just need an Option
that accepts raw data and sets rp.signer
from raw config.
It can be something like WithClientKeyRaw(key []byte)
or WithClientKeyConfig(cfg *client.KeyFile)
Is your feature request related to a problem? Please describe.
I'm using the oidc library as both client and server. When using it as a client, I need a server to test against (not my own, since my own is a proxy). The example server isn't configurable enough to use in tests.
Describe the solution you'd like
What I would like to do is make changes to the example server so that it's more robust and has Go interface.
Describe alternatives you've considered
My concern is that the purpose of the example server is mostly to be documentation. Anything I do to it to give it additional features will obscure the documentation it provides.
The features I need are:
main
package to a sub-package and then just calling it from main
.Additional context
My basic question is: if I do this work as described above, would it be merged or would it be rejected because adding features makes the example not quite as good documentation as it was?
I've already started. If the answer is: not merged, then I'll simply copy the code into my own repo.
Describe the bug
Couldn't get OIDC RP with PKCE working with Keycloak. It seems Keycloak is checking the length of the code_verifier
. While you're using a UUID for the verifier which is 36 chars, the spec says it needs to be at least 43 chars:
https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
Describe the bug
AWS Cognito returns userinfo with email_verified field as text.
"userinfo failed: failed to unmarshal response: json: cannot unmarshal string into Go struct field .email_verified of type bool..."
To Reproduce
Steps to reproduce the behavior:
examples
folder.Expected behavior
Should read userinfo.
In order to improve our commitment to ZITADEL with its libraries and tools being open source, we will relocate this repository to the newly created ZITADEL organisation.
Beginning from 27.04.2022 this repository will be newly located here -> oidc
To migrate your go imports please execute the following command in your projects directory:
find ./ -type f -name "*.go" -o -name "go.mod" -print0 | xargs -0 sed -i '' -e "s/github.com\/caos\/oidc/github.com\/zitadel\/oidc/"
As by Github's documentation we recommend the following:
All links to the previous repository location are automatically redirected to the new location. When you use git clone, git fetch, or git push on a transferred repository, these commands will redirect to the new repository location or URL. However, to avoid confusion, we strongly recommend updating any existing local clones to point to the new repository URL.
git remote set-url origin [email protected]:zitadel/oidc.git
This change will happen in parallel to our release of the version 2 of this library with breaking changes mentioned in #173
master
branch failed. 🚨I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this 💪.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here is some links that can help you:
If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.
package.json
file.A package.json file at the root of your project is required to release on npm.
Please follow the npm guideline to create a valid package.json
file.
Good luck with your project ✨
Your semantic-release bot 📦🚀
Describe the bug
Currently client.Discover
will fail if the provided issuer
doesn't match the returned issuer
. However this validation is too strict as it will fail with oidc.ErrIssuerInvalid
even if i provide https://my.oidc.com
in the function parameter but the returned value will be https://my.oidc.com/
(real use case I encountered).
Expected behavior
I expect discover to succeed if the returned issuer "starts with" the provided issuer or have an option to disable this verification.
As a developer I want to be able to receive a JWT access token when using JWT profile grant.
Acceptance Criteria
Addtional Context
When running go generate ./...
on in the project root, it fails with:
prog.go:14:2: no required module provides package github.com/zitadel/oidc/pkg/rp; to add it:
go get github.com/zitadel/oidc/pkg/rp
prog.go:12:2: no required module provides package github.com/golang/mock/mockgen/model: go.mod file not found in current directory or any parent directory; see 'go help modules'
prog.go:14:2: no required module provides package github.com/zitadel/oidc/pkg/rp: go.mod file not found in current directory or any parent directory; see 'go help modules'
2023/02/17 09:44:05 Loading input failed: exit status 1
generate.go:3: running "mockgen": exit status 1
oidc/pkg/client/rp/mock/generate.go
Line 3 in c8d61c0
There are 2 issues here:
rp
package has changed to github.com/zitadel/oidc/pkg/client/rp
;Verifier
in neither the client
or rp
package;Does somebody know what happened? What would be the correct type and package path?
Is your feature request related to a problem? Please describe.
My login information is provided a legacy system, not compliant to any standard. It's two-phased and reads quite usual:
I'm able to "wrap" this legacy login into OIDC compliant id_token
with zitadel/oidc
, by implementing these to steps within CheckUsernamePassword(username, password, id string) error
from the example. ✅
But later, I need the original token from step 1 to call other APIs from the legacy system.
In addition, I would like to add other information from the two calls as well, like some user roles that are defined in that legacy system.
What I'm trying to achieve is to transport the original token from the login to my backend system via the id_token
.
I was already able to append the information the implementation of the op.AuthRequest
interface.
Describe the solution you'd like
Currently, during the login process, op.CreateIDToken()
is called.
This calls OPStorage.SetUserinfoFromScopes(). In the example in example/server/storage/storage.go
this call fills firstname, phone etc..
I would suggest to extend that call so it contains the op.AuthRequest
from op.CreateIDToken
. Then I could copy the information from that request to the id_token
.
This must be done backwards compatible, of course.
Alternatively, a second call function to copy "custom attributes" might be a solution.
Describe alternatives you've considered
I could save the original token in some persistent store, so that my backend systems could fetch it from there once its needed, but this would break the "self containment" of the id_token, at least somehow.
Additional context
I'd be happy to provide a PR, but maybe there are other ideas or even vetos against such a feature.
Is your feature request related to a problem? Please describe.
I want to authenticate my smart device which has no web browser with my phone. The https://oauth.net/2/device-flow/ flow fixes this.
It's quite commonly used in IoT and smart TVs. It's also used by some cloud CLIs (like awscli) to implement single sign on
Describe the solution you'd like
Implement the https://oauth.net/2/device-flow/ flow
Describe alternatives you've considered
none
Additional context
https://oauth.net/2/device-flow/
Is your feature request related to a problem? Please describe.
In our service we need to get all claims. Currently, UserInfo allows getting only known claims by name.
Describe the solution you'd like
Just additional method GetClaims() map[string]any
in UserInfo
interface
As a developer i want to get the full error so that i am able to identify the potential cause of it.
Is your feature request related to a problem? Please describe.
The client/rp provides a way to save a state
during the login flow. To do this, the rp.AuthURLHandler
func accepts a stateFn func() string
argument.
However I would like my state
to be dependent on the request (to extract some request parameters, path or query).
Describe the solution you'd like
Change the argument to accept a func(*http.Request) string
instead.
Describe alternatives you've considered
Wrap the rp.AuthURLHandler
into a handler which provides a custom stateFn
depending on the request.
Additional context
This would be a breaking change (trivial to fix for the caller, but still breaking, strictly speaking).
To make it non breaking, one could add a new func AuthURLRedirect
(or some other name) and deprecate AuthURLHandler
:
//AuthURLRedirect extends the `AuthURL` method with a http redirect handler
//including handling setting cookie for secure `state` transfer
func AuthURLRedirect(stateFn func(*http.Request) string, rp RelyingParty) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
opts := make([]AuthURLOpt, 0)
state := stateFn(r)
...
}
}
//AuthURLHandler extends the `AuthURL` method with a http redirect handler
//including handling setting cookie for secure `state` transfer
//
//deprecated: use AuthURLRedirect
func AuthURLHandler(stateFn func() string, rp RelyingParty) http.HandlerFunc {
return AuthURLRedirect(func(*http.Request) string { return stateFn() }, rp)
}
I would be willing to craft a PR I you think that this is a good idea.
I have no clear picture about this right now, but it seems there are not that many alternatives around, so I created this issue coreos/go-oidc#305 and had a look at https://openid.net/developers/certified/ also no go library.
I basically agree with https://github.com/caos/oidc#why-another-library but what are the other libraries you looked at and what are your goals, e.g. certification or ?
How do i implement the REST Server Part of the Code Flow Authentication in combination with a SPA ?
Like statet here: https://security.stackexchange.com/questions/129928/oidc-flow-for-spa-and-restful-api
**Authorization Code Flow**
1. User navigates to SPA, which redirects user to IdP to sign in.
2. User signs in (and authorizes the application, if needed).
3. IdP returns user to SPA with Authorization Code.
4. JavaScript code in SPA sends the Authorization Code to a login endpoint on the REST API Server.
5. The REST API Server sends a request to the IdP Server containing the Authorization Code (and usually also a Client ID and Client Secret which identify the REST API Server to the IdP server).
6. The IdP validates the Authorization Code and sends the Access Token and ID Token to the REST API Server.
7. The REST API Server stores the Access Token and ID Token in its memory, and sends its own Session Token back to the SPA.
8. For every request the SPA makes to the REST API Server, it includes the Session Token which the REST API Server gave it. If the REST API Server needs to request resources from another server, it uses the stored Access Token to make that request.
Any help with that? Or hints what to do?
Thansk and regards, fl0w
Is your feature request related to a problem? Please describe.
When creating CLI or native apps the device code flow is the preferred grant type to get access tokens into a users environment.
Describe the solution you'd like
Examples and logic for supporting the device code flow in this library would be amazing. I would be happy to contribute.
Describe alternatives you've considered
The only golang library I've seen implement the device code flow on github is solid. It's a fairly basic flow and shouldn't be too difficult to implement.
Describe the bug
kid
is missing after in jwt access token issuing
To Reproduce
Steps to reproduce the behavior:
op.AccessTokenTypeJWT
access token typeoidc.GrantTypeCode
flow/oauth/token
endpoint does not contains kid
in its headerExpected behavior
Issued access token should contains kid
in its header
Describe the bug
Starting an OP with an Issuer URL that contains a path breaks the endpoint handling.
To Reproduce
Steps to reproduce the behavior:
diff --git a/example/server/default/default.go b/example/server/default/default.go
index 7edaf2e..1877218 100644
--- a/example/server/default/default.go
+++ b/example/server/default/default.go
@@ -17,7 +17,7 @@ func main() {
ctx := context.Background()
port := "9998"
config := &op.Config{
- Issuer: "http://localhost:9998/",
+ Issuer: "http://localhost:9998/path/to/my/op",
CryptoKey: sha256.Sum256([]byte("test")),
}
storage := mock.NewAuthStorage()
@@ -26,7 +26,7 @@ func main() {
log.Fatal(err)
}
router := handler.HttpHandler().(*mux.Router)
- router.Methods("GET").Path("/login").HandlerFunc(HandleLogin)
+ router.Methods("GET").Path("/path/to/my/op/login").HandlerFunc(HandleLogin)
router.Methods("POST").Path("/login").HandlerFunc(HandleCallback)
server := &http.Server{
Addr: ":" + port,
@@ -68,5 +68,5 @@ func HandleLogin(w http.ResponseWriter, r *http.Request) {
func HandleCallback(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
client := r.FormValue("client")
- http.Redirect(w, r, "/authorize/callback?id="+client, http.StatusFound)
+ http.Redirect(w, r, "/path/to/my/op/authorize/callback?id="+client, http.StatusFound)
}
CAOS_OIDC_DEV=1 go run github.com/caos/oidc/example/server/default
Expected behavior
http://localhost:9998/path/to/my/op
, I expect the Discovery Endpoint to be:curl http://localhost:9998/path/to/my/op/.well-known/openid-configuration <- 404 Not Found
but instead it does not contain the path of my Issuer URL:
curl http://localhost:9998/.well-known/openid-configuration <- 200 OK
curl http://localhost:9998/.well-known/openid-configuration | jq
{
"issuer": "http://localhost:9998/path/to/my/op",
"authorization_endpoint": "http://localhost:9998/path/to/my/op/authorize",
"token_endpoint": "http://localhost:9998/path/to/my/op/test",
"introspection_endpoint": "http://localhost:9998/path/to/my/op/oauth/introspect",
"userinfo_endpoint": "http://localhost:9998/path/to/my/op/userinfo",
"revocation_endpoint": "http://localhost:9998/path/to/my/op/revoke",
"end_session_endpoint": "http://localhost:9998/path/to/my/op/end_session",
"jwks_uri": "http://localhost:9998/path/to/my/op/keys",
"scopes_supported": [
(...)
curl http://localhost:9998/path/to/my/op/authorize <- 404 Not Found
Screenshots
N/A
Desktop (please complete the following information):
N/A
Smartphone (please complete the following information):
N/A
Additional context
N/A
As a developer I want to be able to use this library with id tokens that are signed with "ES256" instead of RS256.
Acceptance Criteria
Describe the bug
rs.Introspect
method inside req is created to inspect the token and host of this request is always be the host of Introspect endpoint host. As of my understanding token issued host and Introspect endpoint can be different in this case token validation will fail.
To Reproduce
This will always fail cause token issued host and the introspect different.
Expected behavior
introspect method should allow req host changes as of my understanding.
I am pretty new to this and maybe this is not a bug rather a question.
Describe the bug
as described here: https://discord.com/channels/927474939156643850/927866013545025566/981120399658082334
if I create the default quickstart react app, and using either Zitadel v1, or v2, setup a client to allow id_token, then configure the app to use id_token response type instead of code, the app doesn't work because the redirect from Zitadel doesn't include the state that the client
Expected behaviour
The redirect should include the state field.
Is your feature request related to a problem? Please describe.
Implementing op
and rp
integrations I had lots of bugs. I only found those bugs by adding 100s of prints to the code.
Describe the solution you'd like
After xop is released (should be in a couple weeks or less), I would like to add logging everywhere. This will require changing many function signatures because either a *xop.Log
or a context.Context
would need to be passed to every function that wants to log and many functions do not currently have a context parameter.
Xop is the right choice because:
Describe alternatives you've considered
Xop is not the right choice because:
Additional context
Describe the bug
The front page README.md is using incorrect terminology:
To Reproduce
Steps to reproduce the behavior:
Expected behavior
According to the OpenID Connect Core specification:
Desktop (please complete the following information):
N/A
Smartphone (please complete the following information):
N/A
Additional context
N/A
Is your feature request related to a problem? Please describe.
The server implementation of /authorize doesn't support the "client_credentials" grant type yet
{
"error":"unsupported_grant_type",
"error_description":"client_credentials not supported"
}
I'd like to make use of the client_credentials grant so that I can implement a solution that allows applications to request service tokens.
The application client would use the "client_credentials" grant to receive a token with a list of scopes that the client has requested and is allowed to use.
In a multi-service architecture this is very useful because it allows services to request service tokens that they can then use to call other APIs.
Describe the solution you'd like
The server library can implement support for the client_credentials grant by:
I'm hoping this would be enough for an MVP solution.
Describe the bug
When I execute the command go run github.com/zitadel/oidc/example/server
, the process seems to hang indefinitely. I don't see anything happening
$ go run github.com/zitadel/oidc/example/server
INFO[0000] signer exchanged signing key caller="/Users/pratikbansal/Downloads/zitadel/oidc/pkg/op/signer.go:83"
<hangs ...>
To Reproduce
Steps to reproduce the behavior:
go run github.com/zitadel/oidc/example/server
Expected behavior
The server should have started
Desktop (please complete the following information):
Broken link
The link at https://github.com/zitadel/oidc/blob/main/README.md?plain=1#L81 is redirected to https://zitadel.com/docs/docs/guides/integrate/login-users, which does not exists
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The link leads to the correct page. I guess it should lead to https://zitadel.com/docs/guides/integrate/login-users
Describe the bug
VerifyAccessToken doesn't work because DecryptToken has not been implemented yet
To Reproduce
Steps to reproduce the behavior:
To use VerifyAccessToken functionality. it supposed to decrypt the access token and add values in claims. Then claims can be verified based on the validations. since DecryptToken not implemented so it doesn't. work
Expected behavior
VerifyAccessToken to work, and claims have as per the claims in Access token
Desktop (please complete the following information):
Hey there,
My knowledge when it comes to hosting an OIDC provider is fairly limited, and I have a couple of questions I hope you'll be able to answer.
For the sake of verbosity, I plan on integrating the server implementation of this library in an existing application. It will therefore live alongside multiple other handlers. Furthermore, I'm only interested in the app client implementation, though I'm not 100% sure what flow each of the folder represent.
Why is there a /healthz
handler registered by the server example? Is it because the server is meant to be run as a standalone application (albeit with some modifications to support endpoints like userinfo, etc.)
What exactly does the t
variable represent here?:
https://github.com/caos/oidc/blob/eb10752e485ced36bd996bcb290c6e617f5ea449/example/internal/mock/storage.go#L118-L122
Why is this function called HandleCallback
? Shouldn't the callback technically be on the client side? From what I understand, it would be more appropriate to name it something like HandleLoginAttempt
?
https://github.com/caos/oidc/blob/eb10752e485ced36bd996bcb290c6e617f5ea449/example/server/default/default.go#L68
If the statement above is accurate, then I think the handler should also be in charge of verifying the credentials (username/password) of the user. If so, how does one convey that the verification of the credentials was successful and convey that data? From what I see, it's just redirecting to another path
https://github.com/caos/oidc/blob/eb10752e485ced36bd996bcb290c6e617f5ea449/example/server/default/default.go#L71
Still in the same function/handler above, assuming we swap the input client
for username
and add an extra input password
in the HandleLogin
handler, we would get something like:
func HandleCallback(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.FormValue("username")
password := r.FormValue("password")
isUsernameAndPasswordValid := DoSomethingToValidateCredentialsHere(username, password)
if !isUsernameAndPasswordValid {
http.Error(w, "invalid username or password", http.StatusUnauthorized)
return
}
// At this point, we've verified that the credentials are valid, but we have to return an id..?
http.Redirect(w, r, "/authorize/callback?id="+id, http.StatusFound)
}
instead of
https://github.com/caos/oidc/blob/eb10752e485ced36bd996bcb290c6e617f5ea449/example/server/default/default.go#L68-L71
which prompts the question, is the id
passed as query parameter in the redirect function expected to be some kind of session id?
I think a diagram -- not just of a typical IODC provider, but of the exact endpoints used in each client example -- would greatly help people in understanding how it works. Normally, I'd offer to do it, alas, like I said, I'm not really knowledgeable when it comes to the implementation of an IODC provider 😅 If I end up getting the gist of it, I'll definitely try to help out with the documentation though.
Is your feature request related to a problem? Please describe.
Big thank for your efforts on this great project!
I want to build an OP based on this project, but the OP example is too fuzzy for me to make the features I want.
Describe the solution you'd like
Add or modify OP examples:
Appreciate your help!
Hi, I'm currently implementing an OIDC RP in Photoprism. So first of all, thank you for this great library!
Describe the bug
No matching JWK found, if no kid
header present in JWT but RemoteKeySet provides a single key with non-empty kid
value. In this case we get "invalid key" error (pkg/client/rp/jwks.go:91)
Expected behavior
Either allow absence of kid
value in this case and try verification, improve error reporting as the key is valid but could't be found, or automatically add kid
to both, the remote key set and the corresponding JWT, if it's not provided by storage implementation.
kid
values are not a MUST, if OP does not provide multiple keys:
Hi all,
Im trying to implement a client using the Implicit flow.
But the question is also more general, I cant find how and where to set up the response_type so that I can change the flow to implicit.
To me its seems that the default flow is the authorization_code flow.
Thanks,
Zarko
As of revision fca6cf9, the LICENSE file has an incomplete copyright notice:
Copyright [yyyy] [name of copyright owner]
I've developed derivative work based on the example/server
code and I need to know the correct copyright holder to give credit and comply with the Apache License.
By the way, thanks a lot for making all this work available under an open-source license.
As a developer I want to be able to configure additional URL parameters for the AuthURLHandler and CodeExchangeHandler so that I don't have to implement and extend my own handlers.
Example: login_hint as parameter, so that the OIDC package can also be used to start a flow with a given username
Acceptance Criteria
Sorry if this is documented somewhere already, but i didn't see it
Describe the bug
Hey folks.
We are experimenting with embedding Zitadel OIDC in NetBird. We took the example project as a foundation, and it seems like everything is alright, except for one point related to the JWT keys endpoint.
Our management service uses the discovery endpoint "/.well-known/openid-configuration"
to fetch the configuration. Then it takes jwks_uri
and fetches JWT keys. For example, the jwks_uri
is this endpoint http://localhost:9998/keys
.
This endpoint returns the following content missing x5c and x5t properties:
{
"keys": [{
"use": "sig",
"kty": "RSA",
"kid": "id",
"alg": "RS256",
"n": "5eEovI1i87BBhBzMsHt1xKbDDpwFkTUgvJBkUQVPTMeWGNDTIyo0ithlfaQR6qSWhX9U752F0IMGo3pQHXnHVs91Qa1y3PeFbk-3Lc1KtmrFWzrXJ46j0sKpB9rbLEO1qT2HZalt-w-B2UAU0suezjWZioRkpDacnbPT_VRaDa3Mlu5MBDea-YBH_uuRrAa-luA8dVLtU_8Cd3tp-W7UoO2qdqJuiAXo9pKOMVhuZQUYqLuYZBxNiAzyy5NcRYkoikkicc2no4NAApWc3A24d6P8-UhFw91oRysU5LwW34eUB1sbCO5VomagLkXpeH2HdaireRLZI_HQLP-fqz_EcQ",
"e": "AQAB"
}]
}
It looks like that the problem is here - these fields are not set.
oidc/example/server/storage/storage.go
Line 317 in 4ac692b
What would be the way to set them?
To Reproduce
Start
cd example/server
go build
./server
http://localhost:9998/keys
in your browserExpected behavior
x5t and x5c props are present in the response
P.S. Not sure if this is a bug at all. Any help on that would be very much appreciated.
This change proposes the use of concrete struct types for Claims
and descendant types, instead of interfaces. By usage of generics, we can let callers replace the standard types with custom type that carry additional properties. This would be a breaking change for the next
branch.
In the rp
package the following function will change their signature:
func VerifyTokens[C oidc.AccessTokenHashGetter](ctx context.Context, accessToken, idTokenString string, v IDTokenVerifier) (claims C, err error)
func VerifyIDToken[C oidc.Claims](ctx context.Context, token string, v IDTokenVerifier) (claims C, err error)
In the op
package the following functions will change their signature:
func VerifyIDTokenHint[C oidc.Claims](ctx context.Context, token string, v IDTokenHintVerifier) (claims C, err error)
func VerifyAccessToken[C oidc.Claims](ctx context.Context, token string, v AccessTokenVerifier) (claims C, err error)
Above type parameters between square brackets ([]
) define the minimum set of methods required to check validity of token claims. Aka, constraints. The existing Claims
interfaces will be reused and supplemented with 2 methods:
GetSignatureAlgorithm() jose.SignatureAlgorithm
migrated from IDTokenClaims
SetSignatureAlgorithm(jose.SignatureAlgorithm)
migrated from ClaimsSignature
Although both methods are not required in all use-cases of Claims
all the current existing implementations of Claims
currently carry the signatureAlg
field.
A new interface AccessTokenHashClaims
with the GetAccessTokenHash() string
method migrated from IDTokenClaims
. Finally oidc
will carry the following interface definitions, used as constraints:
type Claims interface {
GetIssuer() string
GetSubject() string
GetAudience() []string
GetExpiration() time.Time
GetIssuedAt() time.Time
GetNonce() string
GetAuthenticationContextClassReference() string
GetAuthTime() time.Time
GetAuthorizedParty() string
// new methods
GetSignatureAlgorithm() jose.SignatureAlgorithm
SetSignatureAlgorithm(jose.SignatureAlgorithm)
}
type AccessTokenHashClaims interface {
Claims
GetAccessTokenHash() string
}
The following interfaces can now be removed (their names will be reused):
AccessTokenClaims
IDTokenClaims
UserInfo
UserInfoProfile
UserInfoEmail
UserInfoPhone
UserInfoAddress
UserInfoSetter
UserInfoProfileSetter
In place, we will export the currently private struct types by taking the above names.
If users want VerifyIDToken
to return the predefined IDTokenClaims
struct type:
claims, err := VerifyIDToken[*oidc.IDTokenClaims](ctx, token, v)
Or if their token caries additional claims, they can extend the type by struct embedding to gain direct access to those claims:
type customClaims struct {
oidc.AccessTokenClaims
Foo string `json:"foo"`
Bar string `json:"bar"`
}
claims, err := VerifyIDToken[*customClaims](ctx, token, v)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.