diff --git a/.forgejo.bak/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
similarity index 99%
rename from .forgejo.bak/ISSUE_TEMPLATE/bug_report.yaml
rename to .github/ISSUE_TEMPLATE/bug_report.yaml
index d024341..92465f9 100644
--- a/.forgejo.bak/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -2,7 +2,6 @@ name: Bug Report
description: "Create a bug report to help us improve ZITADEL. Click [here](https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#product-management) to see how we process your issue."
title: "[Bug]: "
labels: ["bug"]
-type: Bug
body:
- type: markdown
attributes:
diff --git a/.forgejo.bak/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
similarity index 100%
rename from .forgejo.bak/ISSUE_TEMPLATE/config.yml
rename to .github/ISSUE_TEMPLATE/config.yml
diff --git a/.forgejo.bak/ISSUE_TEMPLATE/docs.yaml b/.github/ISSUE_TEMPLATE/docs.yaml
similarity index 98%
rename from .forgejo.bak/ISSUE_TEMPLATE/docs.yaml
rename to .github/ISSUE_TEMPLATE/docs.yaml
index d3f82b9..04c1c0c 100644
--- a/.forgejo.bak/ISSUE_TEMPLATE/docs.yaml
+++ b/.github/ISSUE_TEMPLATE/docs.yaml
@@ -1,7 +1,6 @@
name: 📄 Documentation
description: Create an issue for missing or wrong documentation.
labels: ["docs"]
-type: task
body:
- type: markdown
attributes:
diff --git a/.forgejo.bak/ISSUE_TEMPLATE/enhancement.yaml b/.github/ISSUE_TEMPLATE/improvement.yaml
similarity index 92%
rename from .forgejo.bak/ISSUE_TEMPLATE/enhancement.yaml
rename to .github/ISSUE_TEMPLATE/improvement.yaml
index ef2103e..2e2ddf4 100644
--- a/.forgejo.bak/ISSUE_TEMPLATE/enhancement.yaml
+++ b/.github/ISSUE_TEMPLATE/improvement.yaml
@@ -1,12 +1,11 @@
name: 🛠️ Improvement
description: "Create an new issue for an improvment in ZITADEL"
-labels: ["enhancement"]
-type: enhancement
+labels: ["improvement"]
body:
- type: markdown
attributes:
value: |
- Thanks for taking the time to fill out this proposal / feature reqeust
+ Thanks for taking the time to fill out this improvement request
- type: checkboxes
id: preflight
attributes:
diff --git a/.github/ISSUE_TEMPLATE/proposal.yaml b/.github/ISSUE_TEMPLATE/proposal.yaml
new file mode 100644
index 0000000..af7acd5
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/proposal.yaml
@@ -0,0 +1,44 @@
+name: 💡 Proposal / Feature request
+description: "Create an issue for a feature request/proposal."
+labels: ["enhancement"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this proposal / feature reqeust
+ - type: checkboxes
+ id: preflight
+ attributes:
+ label: Preflight Checklist
+ options:
+ - label:
+ I could not find a solution in the existing issues, docs, nor discussions
+ required: true
+ - label:
+ I have joined the [ZITADEL chat](https://zitadel.com/chat)
+ - type: textarea
+ id: problem
+ attributes:
+ label: Describe your problem
+ description: Please describe your problem this proposal / feature is supposed to solve.
+ placeholder: Describe the problem you have.
+ validations:
+ required: true
+ - type: textarea
+ id: solution
+ attributes:
+ label: Describe your ideal solution
+ description: Which solution do you propose?
+ placeholder: As a [type of user], I want [some goal] so that [some reason].
+ validations:
+ required: true
+ - type: input
+ id: version
+ attributes:
+ label: Version
+ description: Which version of the OIDC Library are you using.
+ - type: textarea
+ id: additional
+ attributes:
+ label: Additional Context
+ description: Please add any other infos that could be useful.
diff --git a/.forgejo.bak/dependabot.yml b/.github/dependabot.yml
similarity index 100%
rename from .forgejo.bak/dependabot.yml
rename to .github/dependabot.yml
diff --git a/.forgejo.bak/pull_request_template.md b/.github/pull_request_template.md
similarity index 100%
rename from .forgejo.bak/pull_request_template.md
rename to .github/pull_request_template.md
diff --git a/.forgejo.bak/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
similarity index 100%
rename from .forgejo.bak/workflows/codeql-analysis.yml
rename to .github/workflows/codeql-analysis.yml
diff --git a/.forgejo.bak/workflows/issue.yml b/.github/workflows/issue.yml
similarity index 94%
rename from .forgejo.bak/workflows/issue.yml
rename to .github/workflows/issue.yml
index 480c339..5b1febf 100644
--- a/.forgejo.bak/workflows/issue.yml
+++ b/.github/workflows/issue.yml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: add issue
- uses: actions/add-to-project@v1.0.2
+ uses: actions/add-to-project@v1.0.1
if: ${{ github.event_name == 'issues' }}
with:
# You can target a repository in a different organization
@@ -28,7 +28,7 @@ jobs:
username: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_PAT }}
- name: add pr
- uses: actions/add-to-project@v1.0.2
+ uses: actions/add-to-project@v1.0.1
if: ${{ github.event_name == 'pull_request_target' && github.actor != 'dependabot[bot]' && !contains(steps.checkUserMember.outputs.teams, 'engineers')}}
with:
# You can target a repository in a different organization
diff --git a/.forgejo.bak/workflows/release.yml b/.github/workflows/release.yml
similarity index 89%
rename from .forgejo.bak/workflows/release.yml
rename to .github/workflows/release.yml
index 00063e4..a6d3826 100644
--- a/.forgejo.bak/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,11 +14,11 @@ on:
jobs:
test:
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
- go: ['1.23', '1.24']
+ go: ['1.21', '1.22']
name: Go ${{ matrix.go }} test
steps:
- uses: actions/checkout@v4
@@ -27,12 +27,12 @@ jobs:
with:
go-version: ${{ matrix.go }}
- run: go test -race -v -coverprofile=profile.cov -coverpkg=./pkg/... ./pkg/...
- - uses: codecov/codecov-action@v5.4.3
+ - uses: codecov/codecov-action@v4.3.0
with:
file: ./profile.cov
name: codecov-go
release:
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-20.04
needs: [test]
if: ${{ github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/next' }}
env:
diff --git a/README.md b/README.md
index bc346f5..01d7d47 100644
--- a/README.md
+++ b/README.md
@@ -21,10 +21,9 @@ Whenever possible we tried to reuse / extend existing packages like `OAuth2 for
## Basic Overview
The most important packages of the library:
-
/pkg
- /client clients using the OP for retrieving, exchanging and verifying tokens
+ /client clients using the OP for retrieving, exchanging and verifying tokens
/rp definition and implementation of an OIDC Relying Party (client)
/rs definition and implementation of an OAuth Resource Server (API)
/op definition and implementation of an OIDC OpenID Provider (server)
@@ -38,6 +37,7 @@ The most important packages of the library:
/server examples of an OpenID Provider implementations (including dynamic) with some very basic login UI
+
### Semver
This package uses [semver](https://semver.org/) for [releases](https://github.com/zitadel/oidc/releases). Major releases ship breaking changes. Starting with the `v2` to `v3` increment we provide an [upgrade guide](UPGRADING.md) to ease migration to a newer version.
@@ -55,84 +55,48 @@ CLIENT_ID=web CLIENT_SECRET=secret ISSUER=http://localhost:9998/ SCOPES="openid
```
- open http://localhost:9999/login in your browser
-- you will be redirected to op server and the login UI
+- you will be redirected to op server and the login UI
- login with user `test-user@localhost` and password `verysecure`
- the OP will redirect you to the client app, which displays the user info
for the dynamic issuer, just start it with:
-
```bash
go run github.com/zitadel/oidc/v3/example/server/dynamic
-```
-
+```
the oidc web client above will still work, but if you add `oidc.local` (pointing to 127.0.0.1) in your hosts file you can also start it with:
-
```bash
CLIENT_ID=web CLIENT_SECRET=secret ISSUER=http://oidc.local:9998/ SCOPES="openid profile" PORT=9999 go run github.com/zitadel/oidc/v3/example/client/app
```
> Note: Usernames are suffixed with the hostname (`test-user@localhost` or `test-user@oidc.local`)
-### Server configuration
-
-Example server allows extra configuration using environment variables and could be used for end to
-end testing of your services.
-
-| Name | Format | Description |
-| ------------ | -------------------------------- | ------------------------------------- |
-| PORT | Number between 1 and 65535 | OIDC listen port |
-| REDIRECT_URI | Comma-separated URIs | List of allowed redirect URIs |
-| USERS_FILE | Path to json in local filesystem | Users with their data and credentials |
-
-Here is json equivalent for one of the default users
-
-```json
-{
- "id2": {
- "ID": "id2",
- "Username": "test-user2",
- "Password": "verysecure",
- "FirstName": "Test",
- "LastName": "User2",
- "Email": "test-user2@zitadel.ch",
- "EmailVerified": true,
- "Phone": "",
- "PhoneVerified": false,
- "PreferredLanguage": "DE",
- "IsAdmin": false
- }
-}
-```
-
## Features
-| | Relying party | OpenID Provider | Specification |
-| -------------------- | ------------- | --------------- | -------------------------------------------- |
-| Code Flow | yes | yes | OpenID Connect Core 1.0, [Section 3.1][1] |
-| Implicit Flow | no[^1] | yes | OpenID Connect Core 1.0, [Section 3.2][2] |
-| Hybrid Flow | no | not yet | OpenID Connect Core 1.0, [Section 3.3][3] |
-| Client Credentials | yes | yes | OpenID Connect Core 1.0, [Section 9][4] |
-| Refresh Token | yes | yes | OpenID Connect Core 1.0, [Section 12][5] |
-| Discovery | yes | yes | OpenID Connect [Discovery][6] 1.0 |
-| JWT Profile | yes | yes | [RFC 7523][7] |
-| PKCE | yes | yes | [RFC 7636][8] |
-| Token Exchange | yes | yes | [RFC 8693][9] |
-| Device Authorization | yes | yes | [RFC 8628][10] |
-| mTLS | not yet | not yet | [RFC 8705][11] |
-| Back-Channel Logout | not yet | yes | OpenID Connect [Back-Channel Logout][12] 1.0 |
+| | Relying party | OpenID Provider | Specification |
+| -------------------- | ------------- | --------------- | ----------------------------------------- |
+| Code Flow | yes | yes | OpenID Connect Core 1.0, [Section 3.1][1] |
+| Implicit Flow | no[^1] | yes | OpenID Connect Core 1.0, [Section 3.2][2] |
+| Hybrid Flow | no | not yet | OpenID Connect Core 1.0, [Section 3.3][3] |
+| Client Credentials | yes | yes | OpenID Connect Core 1.0, [Section 9][4] |
+| Refresh Token | yes | yes | OpenID Connect Core 1.0, [Section 12][5] |
+| Discovery | yes | yes | OpenID Connect [Discovery][6] 1.0 |
+| JWT Profile | yes | yes | [RFC 7523][7] |
+| PKCE | yes | yes | [RFC 7636][8] |
+| Token Exchange | yes | yes | [RFC 8693][9] |
+| Device Authorization | yes | yes | [RFC 8628][10] |
+| mTLS | not yet | not yet | [RFC 8705][11] |
-[1]: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth "3.1. Authentication using the Authorization Code Flow"
-[2]: https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth "3.2. Authentication using the Implicit Flow"
-[3]: https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth "3.3. Authentication using the Hybrid Flow"
-[4]: https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication "9. Client Authentication"
-[5]: https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens "12. Using Refresh Tokens"
-[6]: https://openid.net/specs/openid-connect-discovery-1_0.html "OpenID Connect Discovery 1.0 incorporating errata set 1"
-[7]: https://www.rfc-editor.org/rfc/rfc7523.html "JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants"
-[8]: https://www.rfc-editor.org/rfc/rfc7636.html "Proof Key for Code Exchange by OAuth Public Clients"
-[9]: https://www.rfc-editor.org/rfc/rfc8693.html "OAuth 2.0 Token Exchange"
-[10]: https://www.rfc-editor.org/rfc/rfc8628.html "OAuth 2.0 Device Authorization Grant"
-[11]: https://www.rfc-editor.org/rfc/rfc8705.html "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens"
-[12]: https://openid.net/specs/openid-connect-backchannel-1_0.html "OpenID Connect Back-Channel Logout 1.0 incorporating errata set 1"
+[1]: "3.1. Authentication using the Authorization Code Flow"
+[2]: "3.2. Authentication using the Implicit Flow"
+[3]: "3.3. Authentication using the Hybrid Flow"
+[4]: "9. Client Authentication"
+[5]: "12. Using Refresh Tokens"
+[6]: "OpenID Connect Discovery 1.0 incorporating errata set 1"
+[7]: "JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants"
+[8]: "Proof Key for Code Exchange by OAuth Public Clients"
+[9]: "OAuth 2.0 Token Exchange"
+[10]: "OAuth 2.0 Device Authorization Grant"
+[11]: "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens"
## Contributors
@@ -151,14 +115,14 @@ For your convenience you can find the relevant guides linked below.
## Supported Go Versions
-For security reasons, we only support and recommend the use of one of the latest two Go versions (:white_check_mark:).
+For security reasons, we only support and recommend the use of one of the latest two Go versions (:white_check_mark:).
Versions that also build are marked with :warning:.
| Version | Supported |
| ------- | ------------------ |
-| <1.23 | :x: |
-| 1.23 | :white_check_mark: |
-| 1.24 | :white_check_mark: |
+| <1.21 | :x: |
+| 1.21 | :white_check_mark: |
+| 1.22 | :white_check_mark: |
## Why another library
@@ -189,4 +153,5 @@ Unless required by applicable law or agreed to in writing, software distributed
AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
+
[^1]: https://github.com/zitadel/oidc/issues/135#issuecomment-950563892
diff --git a/example/client/api/api.go b/example/client/api/api.go
index 69f9466..2e61c21 100644
--- a/example/client/api/api.go
+++ b/example/client/api/api.go
@@ -13,8 +13,8 @@ import (
"github.com/go-chi/chi/v5"
"github.com/sirupsen/logrus"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rs"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client/rs"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
const (
diff --git a/example/client/app/app.go b/example/client/app/app.go
index 90b1969..99aba3d 100644
--- a/example/client/app/app.go
+++ b/example/client/app/app.go
@@ -14,10 +14,10 @@ import (
"github.com/google/uuid"
"github.com/sirupsen/logrus"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/zitadel/logging"
+ "github.com/zitadel/oidc/v3/pkg/client/rp"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
var (
@@ -56,7 +56,6 @@ func main() {
rp.WithVerifierOpts(rp.WithIssuedAtOffset(5 * time.Second)),
rp.WithHTTPClient(client),
rp.WithLogger(logger),
- rp.WithSigningAlgsFromDiscovery(),
}
if clientSecret == "" {
options = append(options, rp.WithPKCE(cookieHandler))
@@ -109,7 +108,6 @@ func main() {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- w.Header().Set("content-type", "application/json")
w.Write(data)
}
diff --git a/example/client/device/device.go b/example/client/device/device.go
index 33bc570..78ed2c8 100644
--- a/example/client/device/device.go
+++ b/example/client/device/device.go
@@ -45,8 +45,8 @@ import (
"github.com/sirupsen/logrus"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/client/rp"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
)
var (
diff --git a/example/client/github/github.go b/example/client/github/github.go
index f6c536b..7d069d4 100644
--- a/example/client/github/github.go
+++ b/example/client/github/github.go
@@ -10,10 +10,10 @@ import (
"golang.org/x/oauth2"
githubOAuth "golang.org/x/oauth2/github"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp/cli"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client/rp"
+ "github.com/zitadel/oidc/v3/pkg/client/rp/cli"
+ "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
var (
diff --git a/example/client/service/service.go b/example/client/service/service.go
index a88ab2f..865a4e0 100644
--- a/example/client/service/service.go
+++ b/example/client/service/service.go
@@ -13,7 +13,7 @@ import (
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/profile"
+ "github.com/zitadel/oidc/v3/pkg/client/profile"
)
var client = http.DefaultClient
diff --git a/example/server/config/config.go b/example/server/config/config.go
deleted file mode 100644
index 96837d4..0000000
--- a/example/server/config/config.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package config
-
-import (
- "os"
- "strings"
-)
-
-const (
- // default port for the http server to run
- DefaultIssuerPort = "9998"
-)
-
-type Config struct {
- Port string
- RedirectURI []string
- UsersFile string
-}
-
-// FromEnvVars loads configuration parameters from environment variables.
-// If there is no such variable defined, then use default values.
-func FromEnvVars(defaults *Config) *Config {
- if defaults == nil {
- defaults = &Config{}
- }
- cfg := &Config{
- Port: defaults.Port,
- RedirectURI: defaults.RedirectURI,
- UsersFile: defaults.UsersFile,
- }
- if value, ok := os.LookupEnv("PORT"); ok {
- cfg.Port = value
- }
- if value, ok := os.LookupEnv("USERS_FILE"); ok {
- cfg.UsersFile = value
- }
- if value, ok := os.LookupEnv("REDIRECT_URI"); ok {
- cfg.RedirectURI = strings.Split(value, ",")
- }
- return cfg
-}
diff --git a/example/server/config/config_test.go b/example/server/config/config_test.go
deleted file mode 100644
index 3b73c0b..0000000
--- a/example/server/config/config_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package config
-
-import (
- "fmt"
- "os"
- "testing"
-)
-
-func TestFromEnvVars(t *testing.T) {
-
- for _, tc := range []struct {
- name string
- env map[string]string
- defaults *Config
- want *Config
- }{
- {
- name: "no vars, no default values",
- env: map[string]string{},
- want: &Config{},
- },
- {
- name: "no vars, only defaults",
- env: map[string]string{},
- defaults: &Config{
- Port: "6666",
- UsersFile: "/default/user/path",
- RedirectURI: []string{"re", "direct", "uris"},
- },
- want: &Config{
- Port: "6666",
- UsersFile: "/default/user/path",
- RedirectURI: []string{"re", "direct", "uris"},
- },
- },
- {
- name: "overriding default values",
- env: map[string]string{
- "PORT": "1234",
- "USERS_FILE": "/path/to/users",
- "REDIRECT_URI": "http://redirect/redirect",
- },
- defaults: &Config{
- Port: "6666",
- UsersFile: "/default/user/path",
- RedirectURI: []string{"re", "direct", "uris"},
- },
- want: &Config{
- Port: "1234",
- UsersFile: "/path/to/users",
- RedirectURI: []string{"http://redirect/redirect"},
- },
- },
- {
- name: "multiple redirect uris",
- env: map[string]string{
- "REDIRECT_URI": "http://host_1,http://host_2,http://host_3",
- },
- want: &Config{
- RedirectURI: []string{
- "http://host_1", "http://host_2", "http://host_3",
- },
- },
- },
- } {
- t.Run(tc.name, func(t *testing.T) {
- os.Clearenv()
- for k, v := range tc.env {
- os.Setenv(k, v)
- }
- cfg := FromEnvVars(tc.defaults)
- if fmt.Sprint(cfg) != fmt.Sprint(tc.want) {
- t.Errorf("Expected FromEnvVars()=%q, but got %q", tc.want, cfg)
- }
- })
- }
-}
diff --git a/example/server/dynamic/login.go b/example/server/dynamic/login.go
index 05f0e34..685b444 100644
--- a/example/server/dynamic/login.go
+++ b/example/server/dynamic/login.go
@@ -8,7 +8,7 @@ import (
"github.com/go-chi/chi/v5"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
const (
diff --git a/example/server/dynamic/op.go b/example/server/dynamic/op.go
index 2c00e41..432a575 100644
--- a/example/server/dynamic/op.go
+++ b/example/server/dynamic/op.go
@@ -10,8 +10,8 @@ import (
"github.com/go-chi/chi/v5"
"golang.org/x/text/language"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/storage"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/example/server/storage"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
const (
diff --git a/example/server/exampleop/device.go b/example/server/exampleop/device.go
index 99505e4..2f9be52 100644
--- a/example/server/exampleop/device.go
+++ b/example/server/exampleop/device.go
@@ -8,10 +8,10 @@ import (
"net/http"
"net/url"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
"github.com/go-chi/chi/v5"
"github.com/gorilla/securecookie"
"github.com/sirupsen/logrus"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
type deviceAuthenticate interface {
diff --git a/example/server/exampleop/login.go b/example/server/exampleop/login.go
index 77a6189..4d2b478 100644
--- a/example/server/exampleop/login.go
+++ b/example/server/exampleop/login.go
@@ -5,8 +5,8 @@ import (
"fmt"
"net/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
"github.com/go-chi/chi/v5"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
type login struct {
diff --git a/example/server/exampleop/op.go b/example/server/exampleop/op.go
index e12c755..e8ef892 100644
--- a/example/server/exampleop/op.go
+++ b/example/server/exampleop/op.go
@@ -12,13 +12,22 @@ import (
"github.com/zitadel/logging"
"golang.org/x/text/language"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/example/server/storage"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
const (
pathLoggedOut = "/logged-out"
)
+func init() {
+ storage.RegisterClients(
+ storage.NativeClient("native"),
+ storage.WebClient("web", "secret"),
+ storage.WebClient("api", "secret"),
+ )
+}
+
type Storage interface {
op.Storage
authenticate
diff --git a/example/server/main.go b/example/server/main.go
index 5bdbb05..a2ad190 100644
--- a/example/server/main.go
+++ b/example/server/main.go
@@ -6,53 +6,36 @@ import (
"net/http"
"os"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/config"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/exampleop"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/storage"
+ "github.com/zitadel/oidc/v3/example/server/exampleop"
+ "github.com/zitadel/oidc/v3/example/server/storage"
)
-func getUserStore(cfg *config.Config) (storage.UserStore, error) {
- if cfg.UsersFile == "" {
- return storage.NewUserStore(fmt.Sprintf("http://localhost:%s/", cfg.Port)), nil
- }
- return storage.StoreFromFile(cfg.UsersFile)
-}
-
func main() {
- cfg := config.FromEnvVars(&config.Config{Port: "9998"})
+ //we will run on :9998
+ port := "9998"
+ //which gives us the issuer: http://localhost:9998/
+ issuer := fmt.Sprintf("http://localhost:%s/", port)
+
+ // the OpenIDProvider interface needs a Storage interface handling various checks and state manipulations
+ // this might be the layer for accessing your database
+ // in this example it will be handled in-memory
+ storage := storage.NewStorage(storage.NewUserStore(issuer))
+
logger := slog.New(
slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
AddSource: true,
Level: slog.LevelDebug,
}),
)
-
- //which gives us the issuer: http://localhost:9998/
- issuer := fmt.Sprintf("http://localhost:%s/", cfg.Port)
-
- storage.RegisterClients(
- storage.NativeClient("native", cfg.RedirectURI...),
- storage.WebClient("web", "secret", cfg.RedirectURI...),
- storage.WebClient("api", "secret", cfg.RedirectURI...),
- )
-
- // the OpenIDProvider interface needs a Storage interface handling various checks and state manipulations
- // this might be the layer for accessing your database
- // in this example it will be handled in-memory
- store, err := getUserStore(cfg)
- if err != nil {
- logger.Error("cannot create UserStore", "error", err)
- os.Exit(1)
- }
- storage := storage.NewStorage(store)
router := exampleop.SetupServer(issuer, storage, logger, false)
server := &http.Server{
- Addr: ":" + cfg.Port,
+ Addr: ":" + port,
Handler: router,
}
- logger.Info("server listening, press ctrl+c to stop", "addr", issuer)
- if server.ListenAndServe() != http.ErrServerClosed {
+ logger.Info("server listening, press ctrl+c to stop", "addr", fmt.Sprintf("http://localhost:%s/", port))
+ err := server.ListenAndServe()
+ if err != http.ErrServerClosed {
logger.Error("server terminated", "error", err)
os.Exit(1)
}
diff --git a/example/server/storage/client.go b/example/server/storage/client.go
index 2b836c0..010b9ce 100644
--- a/example/server/storage/client.go
+++ b/example/server/storage/client.go
@@ -3,8 +3,8 @@ package storage
import (
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
var (
diff --git a/example/server/storage/oidc.go b/example/server/storage/oidc.go
index 9c7f544..9cd08d9 100644
--- a/example/server/storage/oidc.go
+++ b/example/server/storage/oidc.go
@@ -6,8 +6,8 @@ import (
"golang.org/x/text/language"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
const (
@@ -121,7 +121,7 @@ func (a *AuthRequest) Done() bool {
}
func PromptToInternal(oidcPrompt oidc.SpaceDelimitedArray) []string {
- prompts := make([]string, 0, len(oidcPrompt))
+ prompts := make([]string, len(oidcPrompt))
for _, oidcPrompt := range oidcPrompt {
switch oidcPrompt {
case oidc.PromptNone,
@@ -164,15 +164,6 @@ func authRequestToInternal(authReq *oidc.AuthRequest, userID string) *AuthReques
}
}
-type AuthRequestWithSessionState struct {
- *AuthRequest
- SessionState string
-}
-
-func (a *AuthRequestWithSessionState) GetSessionState() string {
- return a.SessionState
-}
-
type OIDCCodeChallenge struct {
Challenge string
Method string
diff --git a/example/server/storage/storage.go b/example/server/storage/storage.go
index d4315c6..d8b7a5d 100644
--- a/example/server/storage/storage.go
+++ b/example/server/storage/storage.go
@@ -14,8 +14,8 @@ import (
jose "github.com/go-jose/go-jose/v4"
"github.com/google/uuid"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
// serviceKey1 is a public key which will be used for the JWT Profile Authorization Grant
@@ -151,9 +151,6 @@ func (s *Storage) CheckUsernamePassword(username, password, id string) error {
// in this example we'll simply check the username / password and set a boolean to true
// therefore we will also just check this boolean if the request / login has been finished
request.done = true
-
- request.authTime = time.Now()
-
return nil
}
return fmt.Errorf("username or password wrong")
@@ -298,19 +295,15 @@ func (s *Storage) CreateAccessAndRefreshTokens(ctx context.Context, request op.T
// if we get here, the currentRefreshToken was not empty, so the call is a refresh token request
// we therefore will have to check the currentRefreshToken and renew the refresh token
-
- newRefreshToken = uuid.NewString()
-
- accessToken, err := s.accessToken(applicationID, newRefreshToken, request.GetSubject(), request.GetAudience(), request.GetScopes())
+ refreshToken, refreshTokenID, err := s.renewRefreshToken(currentRefreshToken)
if err != nil {
return "", "", time.Time{}, err
}
-
- if err := s.renewRefreshToken(currentRefreshToken, newRefreshToken, accessToken.ID); err != nil {
+ accessToken, err := s.accessToken(applicationID, refreshTokenID, request.GetSubject(), request.GetAudience(), request.GetScopes())
+ if err != nil {
return "", "", time.Time{}, err
}
-
- return accessToken.ID, newRefreshToken, accessToken.Expiration, nil
+ return accessToken.ID, refreshToken, accessToken.Expiration, nil
}
func (s *Storage) exchangeRefreshToken(ctx context.Context, request op.TokenExchangeRequest) (accessTokenID string, newRefreshToken string, expiration time.Time, err error) {
@@ -392,9 +385,14 @@ func (s *Storage) RevokeToken(ctx context.Context, tokenIDOrToken string, userID
if refreshToken.ApplicationID != clientID {
return oidc.ErrInvalidClient().WithDescription("token was not issued for this client")
}
- delete(s.refreshTokens, refreshToken.ID)
// if it is a refresh token, you will have to remove the access token as well
- delete(s.tokens, refreshToken.AccessToken)
+ delete(s.refreshTokens, refreshToken.ID)
+ for _, accessToken := range s.tokens {
+ if accessToken.RefreshTokenID == refreshToken.ID {
+ delete(s.tokens, accessToken.ID)
+ return nil
+ }
+ }
return nil
}
@@ -490,9 +488,6 @@ func (s *Storage) SetUserinfoFromToken(ctx context.Context, userinfo *oidc.UserI
// return err
// }
//}
- if token.Expiration.Before(time.Now()) {
- return fmt.Errorf("token is expired")
- }
return s.setUserinfo(ctx, userinfo, token.Subject, token.ApplicationID, token.Scopes)
}
@@ -599,41 +594,33 @@ func (s *Storage) createRefreshToken(accessToken *Token, amr []string, authTime
Audience: accessToken.Audience,
Expiration: time.Now().Add(5 * time.Hour),
Scopes: accessToken.Scopes,
- AccessToken: accessToken.ID,
}
s.refreshTokens[token.ID] = token
return token.Token, nil
}
// renewRefreshToken checks the provided refresh_token and creates a new one based on the current
-//
-// [Refresh Token Rotation] is implemented.
-//
-// [Refresh Token Rotation]: https://www.rfc-editor.org/rfc/rfc6819#section-5.2.2.3
-func (s *Storage) renewRefreshToken(currentRefreshToken, newRefreshToken, newAccessToken string) error {
+func (s *Storage) renewRefreshToken(currentRefreshToken string) (string, string, error) {
s.lock.Lock()
defer s.lock.Unlock()
refreshToken, ok := s.refreshTokens[currentRefreshToken]
if !ok {
- return fmt.Errorf("invalid refresh token")
+ return "", "", fmt.Errorf("invalid refresh token")
}
- // deletes the refresh token
+ // deletes the refresh token and all access tokens which were issued based on this refresh token
delete(s.refreshTokens, currentRefreshToken)
-
- // delete the access token which was issued based on this refresh token
- delete(s.tokens, refreshToken.AccessToken)
-
- if refreshToken.Expiration.Before(time.Now()) {
- return fmt.Errorf("expired refresh token")
+ for _, token := range s.tokens {
+ if token.RefreshTokenID == currentRefreshToken {
+ delete(s.tokens, token.ID)
+ break
+ }
}
-
// creates a new refresh token based on the current one
- refreshToken.Token = newRefreshToken
- refreshToken.ID = newRefreshToken
- refreshToken.Expiration = time.Now().Add(5 * time.Hour)
- refreshToken.AccessToken = newAccessToken
- s.refreshTokens[newRefreshToken] = refreshToken
- return nil
+ token := uuid.NewString()
+ refreshToken.Token = token
+ refreshToken.ID = token
+ s.refreshTokens[token] = refreshToken
+ return token, refreshToken.ID, nil
}
// accessToken will store an access_token in-memory based on the provided information
diff --git a/example/server/storage/storage_dynamic.go b/example/server/storage/storage_dynamic.go
index 765d29a..d112d71 100644
--- a/example/server/storage/storage_dynamic.go
+++ b/example/server/storage/storage_dynamic.go
@@ -6,8 +6,8 @@ import (
jose "github.com/go-jose/go-jose/v4"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
type multiStorage struct {
diff --git a/example/server/storage/token.go b/example/server/storage/token.go
index beab38c..ad907e3 100644
--- a/example/server/storage/token.go
+++ b/example/server/storage/token.go
@@ -22,5 +22,4 @@ type RefreshToken struct {
ApplicationID string
Expiration time.Time
Scopes []string
- AccessToken string // Token.ID
}
diff --git a/example/server/storage/user.go b/example/server/storage/user.go
index ed8cdfa..173daef 100644
--- a/example/server/storage/user.go
+++ b/example/server/storage/user.go
@@ -2,8 +2,6 @@ package storage
import (
"crypto/rsa"
- "encoding/json"
- "os"
"strings"
"golang.org/x/text/language"
@@ -37,18 +35,6 @@ type userStore struct {
users map[string]*User
}
-func StoreFromFile(path string) (UserStore, error) {
- users := map[string]*User{}
- data, err := os.ReadFile(path)
- if err != nil {
- return nil, err
- }
- if err := json.Unmarshal(data, &users); err != nil {
- return nil, err
- }
- return userStore{users}, nil
-}
-
func NewUserStore(issuer string) UserStore {
hostname := strings.Split(strings.Split(issuer, "://")[1], ":")[0]
return userStore{
diff --git a/example/server/storage/user_test.go b/example/server/storage/user_test.go
deleted file mode 100644
index c2e2212..0000000
--- a/example/server/storage/user_test.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package storage
-
-import (
- "os"
- "path"
- "reflect"
- "testing"
-
- "golang.org/x/text/language"
-)
-
-func TestStoreFromFile(t *testing.T) {
- for _, tc := range []struct {
- name string
- pathToFile string
- content string
- want UserStore
- wantErr bool
- }{
- {
- name: "normal user file",
- pathToFile: "userfile.json",
- content: `{
- "id1": {
- "ID": "id1",
- "EmailVerified": true,
- "PreferredLanguage": "DE"
- }
- }`,
- want: userStore{map[string]*User{
- "id1": {
- ID: "id1",
- EmailVerified: true,
- PreferredLanguage: language.German,
- },
- }},
- },
- {
- name: "malformed file",
- pathToFile: "whatever",
- content: "not a json just a text",
- wantErr: true,
- },
- {
- name: "not existing file",
- pathToFile: "what/ever/file",
- wantErr: true,
- },
- } {
- t.Run(tc.name, func(t *testing.T) {
- actualPath := path.Join(t.TempDir(), tc.pathToFile)
-
- if tc.content != "" && tc.pathToFile != "" {
- if err := os.WriteFile(actualPath, []byte(tc.content), 0666); err != nil {
- t.Fatalf("cannot create file with test content: %q", tc.content)
- }
- }
- result, err := StoreFromFile(actualPath)
- if err != nil && !tc.wantErr {
- t.Errorf("StoreFromFile(%q) returned unexpected error %q", tc.pathToFile, err)
- } else if err == nil && tc.wantErr {
- t.Errorf("StoreFromFile(%q) did not return an expected error", tc.pathToFile)
- }
- if !tc.wantErr && !reflect.DeepEqual(tc.want, result.(userStore)) {
- t.Errorf("expected StoreFromFile(%q) = %v, but got %v",
- tc.pathToFile, tc.want, result)
- }
- })
- }
-}
diff --git a/go.mod b/go.mod
index a0f42c4..80e8933 100644
--- a/go.mod
+++ b/go.mod
@@ -1,40 +1,38 @@
-module git.christmann.info/LARA/zitadel-oidc/v3
+module github.com/zitadel/oidc/v3
-go 1.23.7
-
-toolchain go1.24.1
+go 1.21
require (
- github.com/bmatcuk/doublestar/v4 v4.8.1
- github.com/go-chi/chi/v5 v5.2.1
- github.com/go-jose/go-jose/v4 v4.0.5
+ github.com/bmatcuk/doublestar/v4 v4.6.1
+ github.com/go-chi/chi/v5 v5.0.12
+ github.com/go-jose/go-jose/v4 v4.0.1
github.com/golang/mock v1.6.0
github.com/google/go-github/v31 v31.0.0
github.com/google/uuid v1.6.0
github.com/gorilla/securecookie v1.1.2
- github.com/jeremija/gosubmit v0.2.8
+ github.com/jeremija/gosubmit v0.2.7
github.com/muhlemmer/gu v0.3.1
github.com/muhlemmer/httpforwarded v0.1.0
- github.com/rs/cors v1.11.1
+ github.com/rs/cors v1.11.0
github.com/sirupsen/logrus v1.9.3
- github.com/stretchr/testify v1.10.0
- github.com/zitadel/logging v0.6.2
- github.com/zitadel/schema v1.3.1
- go.opentelemetry.io/otel v1.29.0
- golang.org/x/oauth2 v0.30.0
- golang.org/x/text v0.26.0
+ github.com/stretchr/testify v1.9.0
+ github.com/zitadel/logging v0.6.0
+ github.com/zitadel/schema v1.3.0
+ go.opentelemetry.io/otel v1.26.0
+ golang.org/x/oauth2 v0.19.0
+ golang.org/x/text v0.14.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/go-logr/logr v1.4.2 // indirect
+ github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- go.opentelemetry.io/otel/metric v1.29.0 // indirect
- go.opentelemetry.io/otel/trace v1.29.0 // indirect
- golang.org/x/crypto v0.36.0 // indirect
- golang.org/x/net v0.38.0 // indirect
- golang.org/x/sys v0.31.0 // indirect
+ go.opentelemetry.io/otel/metric v1.26.0 // indirect
+ go.opentelemetry.io/otel/trace v1.26.0 // indirect
+ golang.org/x/crypto v0.22.0 // indirect
+ golang.org/x/net v0.23.0 // indirect
+ golang.org/x/sys v0.19.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 4835505..2034402 100644
--- a/go.sum
+++ b/go.sum
@@ -1,15 +1,15 @@
-github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
-github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
+github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
+github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
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/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
-github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
-github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
-github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
+github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
+github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
-github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
@@ -29,8 +29,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
-github.com/jeremija/gosubmit v0.2.8 h1:mmSITBz9JxVtu8eqbN+zmmwX7Ij2RidQxhcwRVI4wqA=
-github.com/jeremija/gosubmit v0.2.8/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI=
+github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqROIc=
+github.com/jeremija/gosubmit v0.2.7/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
@@ -41,40 +41,40 @@ github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/
github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
-github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
+github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
+github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/zitadel/logging v0.6.2 h1:MW2kDDR0ieQynPZ0KIZPrh9ote2WkxfBif5QoARDQcU=
-github.com/zitadel/logging v0.6.2/go.mod h1:z6VWLWUkJpnNVDSLzrPSQSQyttysKZ6bCRongw0ROK4=
-github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU=
-github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU=
-go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
-go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
-go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
-go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
-go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
-go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
+github.com/zitadel/logging v0.6.0 h1:t5Nnt//r+m2ZhhoTmoPX+c96pbMarqJvW1Vq6xFTank=
+github.com/zitadel/logging v0.6.0/go.mod h1:Y4CyAXHpl3Mig6JOszcV5Rqqsojj+3n7y2F591Mp/ow=
+github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0=
+github.com/zitadel/schema v1.3.0/go.mod h1:NptN6mkBDFvERUCvZHlvWmmME+gmZ44xzwRXwhzsbtc=
+go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs=
+go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4=
+go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30=
+go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4=
+go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA=
+go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
-golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
+golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
+golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
-golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
-golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
+golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
+golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -83,13 +83,13 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
-golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
+golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
-golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@@ -101,8 +101,8 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/internal/testutil/gen/gen.go b/internal/testutil/gen/gen.go
index 3e44b7d..e4a5718 100644
--- a/internal/testutil/gen/gen.go
+++ b/internal/testutil/gen/gen.go
@@ -8,8 +8,8 @@ import (
"fmt"
"os"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
var custom = map[string]any{
diff --git a/internal/testutil/token.go b/internal/testutil/token.go
index 72d08c5..7ad8893 100644
--- a/internal/testutil/token.go
+++ b/internal/testutil/token.go
@@ -8,9 +8,9 @@ import (
"errors"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
jose "github.com/go-jose/go-jose/v4"
"github.com/muhlemmer/gu"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// KeySet implements oidc.Keys
diff --git a/pkg/client/client.go b/pkg/client/client.go
index 2e1f536..e17c70a 100644
--- a/pkg/client/client.go
+++ b/pkg/client/client.go
@@ -12,12 +12,11 @@ import (
"github.com/go-jose/go-jose/v4"
"github.com/zitadel/logging"
+ "github.com/zitadel/oidc/v3/pkg/crypto"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
"go.opentelemetry.io/otel"
"golang.org/x/oauth2"
-
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/crypto"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
)
var (
@@ -42,7 +41,7 @@ func Discover(ctx context.Context, issuer string, httpClient *http.Client, wellK
discoveryConfig := new(oidc.DiscoveryConfiguration)
err = httphelper.HttpRequest(httpClient, req, &discoveryConfig)
if err != nil {
- return nil, errors.Join(oidc.ErrDiscoveryFailed, err)
+ return nil, err
}
if logger, ok := logging.FromContext(ctx); ok {
logger.Debug("discover", "config", discoveryConfig)
@@ -197,12 +196,12 @@ func CallTokenExchangeEndpoint(ctx context.Context, request any, authFn any, cal
}
func NewSignerFromPrivateKeyByte(key []byte, keyID string) (jose.Signer, error) {
- privateKey, algorithm, err := crypto.BytesToPrivateKey(key)
+ privateKey, err := crypto.BytesToPrivateKey(key)
if err != nil {
return nil, err
}
signingKey := jose.SigningKey{
- Algorithm: algorithm,
+ Algorithm: jose.RS256,
Key: &jose.JSONWebKey{Key: privateKey, KeyID: keyID},
}
return jose.NewSigner(signingKey, &jose.SignerOptions{})
diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go
index 9e21e8e..e06c825 100644
--- a/pkg/client/client_test.go
+++ b/pkg/client/client_test.go
@@ -5,7 +5,6 @@ import (
"net/http"
"testing"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -23,7 +22,7 @@ func TestDiscover(t *testing.T) {
name string
args args
wantFields *wantFields
- wantErr error
+ wantErr bool
}{
{
name: "spotify", // https://github.com/zitadel/oidc/issues/406
@@ -33,20 +32,17 @@ func TestDiscover(t *testing.T) {
wantFields: &wantFields{
UILocalesSupported: true,
},
- wantErr: nil,
- },
- {
- name: "discovery failed",
- args: args{
- issuer: "https://example.com",
- },
- wantErr: oidc.ErrDiscoveryFailed,
+ wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Discover(context.Background(), tt.args.issuer, http.DefaultClient, tt.args.wellKnownUrl...)
- require.ErrorIs(t, err, tt.wantErr)
+ if tt.wantErr {
+ assert.Error(t, err)
+ return
+ }
+ require.NoError(t, err)
if tt.wantFields == nil {
return
}
diff --git a/pkg/client/integration_test.go b/pkg/client/integration_test.go
index 86a9ab7..98a9d3a 100644
--- a/pkg/client/integration_test.go
+++ b/pkg/client/integration_test.go
@@ -23,14 +23,14 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/exampleop"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/storage"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rs"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/tokenexchange"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/example/server/exampleop"
+ "github.com/zitadel/oidc/v3/example/server/storage"
+ "github.com/zitadel/oidc/v3/pkg/client/rp"
+ "github.com/zitadel/oidc/v3/pkg/client/rs"
+ "github.com/zitadel/oidc/v3/pkg/client/tokenexchange"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
var Logger = slog.New(
diff --git a/pkg/client/jwt_profile.go b/pkg/client/jwt_profile.go
index 98a54fd..0a5d9ec 100644
--- a/pkg/client/jwt_profile.go
+++ b/pkg/client/jwt_profile.go
@@ -6,8 +6,8 @@ import (
"golang.org/x/oauth2"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// JWTProfileExchange handles the oauth2 jwt profile exchange
diff --git a/pkg/client/key.go b/pkg/client/key.go
index 7f38311..0c01dd2 100644
--- a/pkg/client/key.go
+++ b/pkg/client/key.go
@@ -2,7 +2,7 @@ package client
import (
"encoding/json"
- "os"
+ "io/ioutil"
)
const (
@@ -24,7 +24,7 @@ type KeyFile struct {
}
func ConfigFromKeyFile(path string) (*KeyFile, error) {
- data, err := os.ReadFile(path)
+ data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
diff --git a/pkg/client/profile/jwt_profile.go b/pkg/client/profile/jwt_profile.go
index fb351f0..060f390 100644
--- a/pkg/client/profile/jwt_profile.go
+++ b/pkg/client/profile/jwt_profile.go
@@ -8,8 +8,8 @@ import (
jose "github.com/go-jose/go-jose/v4"
"golang.org/x/oauth2"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type TokenSource interface {
diff --git a/pkg/client/rp/cli/cli.go b/pkg/client/rp/cli/cli.go
index 10edaa7..eeb9011 100644
--- a/pkg/client/rp/cli/cli.go
+++ b/pkg/client/rp/cli/cli.go
@@ -4,9 +4,9 @@ import (
"context"
"net/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client/rp"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
const (
diff --git a/pkg/client/rp/delegation.go b/pkg/client/rp/delegation.go
index fb4fc63..23ecffd 100644
--- a/pkg/client/rp/delegation.go
+++ b/pkg/client/rp/delegation.go
@@ -1,7 +1,7 @@
package rp
import (
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc/grants/tokenexchange"
+ "github.com/zitadel/oidc/v3/pkg/oidc/grants/tokenexchange"
)
// DelegationTokenRequest is an implementation of TokenExchangeRequest
diff --git a/pkg/client/rp/device.go b/pkg/client/rp/device.go
index 1fadd56..c2d1f8a 100644
--- a/pkg/client/rp/device.go
+++ b/pkg/client/rp/device.go
@@ -5,8 +5,8 @@ import (
"fmt"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
func newDeviceClientCredentialsRequest(scopes []string, rp RelyingParty) (*oidc.ClientCredentialsRequest, error) {
diff --git a/pkg/client/rp/jwks.go b/pkg/client/rp/jwks.go
index 0ccbad2..c44a267 100644
--- a/pkg/client/rp/jwks.go
+++ b/pkg/client/rp/jwks.go
@@ -9,9 +9,9 @@ import (
jose "github.com/go-jose/go-jose/v4"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
func NewRemoteKeySet(client *http.Client, jwksURL string, opts ...func(*remoteKeySet)) oidc.KeySet {
diff --git a/pkg/client/rp/relying_party.go b/pkg/client/rp/relying_party.go
index c2759a2..ac7f466 100644
--- a/pkg/client/rp/relying_party.go
+++ b/pkg/client/rp/relying_party.go
@@ -14,10 +14,10 @@ import (
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/zitadel/logging"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
const (
@@ -541,7 +541,7 @@ func CodeExchangeHandler[C oidc.IDClaims](callback CodeExchangeCallback[C], rp R
rp.CookieHandler().DeleteCookie(w, pkceCode)
}
if rp.Signer() != nil {
- assertion, err := client.SignedJWTProfileAssertion(rp.OAuthConfig().ClientID, []string{rp.Issuer(), rp.OAuthConfig().Endpoint.TokenURL}, time.Hour, rp.Signer())
+ assertion, err := client.SignedJWTProfileAssertion(rp.OAuthConfig().ClientID, []string{rp.Issuer()}, time.Hour, rp.Signer())
if err != nil {
unauthorizedError(w, r, "failed to build assertion: "+err.Error(), state, rp)
return
@@ -734,11 +734,11 @@ func (t tokenEndpointCaller) TokenEndpoint() string {
type RefreshTokenRequest struct {
RefreshToken string `schema:"refresh_token"`
- Scopes oidc.SpaceDelimitedArray `schema:"scope,omitempty"`
- ClientID string `schema:"client_id,omitempty"`
- ClientSecret string `schema:"client_secret,omitempty"`
- ClientAssertion string `schema:"client_assertion,omitempty"`
- ClientAssertionType string `schema:"client_assertion_type,omitempty"`
+ Scopes oidc.SpaceDelimitedArray `schema:"scope"`
+ ClientID string `schema:"client_id"`
+ ClientSecret string `schema:"client_secret"`
+ ClientAssertion string `schema:"client_assertion"`
+ ClientAssertionType string `schema:"client_assertion_type"`
GrantType oidc.GrantType `schema:"grant_type"`
}
diff --git a/pkg/client/rp/relying_party_test.go b/pkg/client/rp/relying_party_test.go
index b3bb6ee..4c5a1b3 100644
--- a/pkg/client/rp/relying_party_test.go
+++ b/pkg/client/rp/relying_party_test.go
@@ -5,10 +5,10 @@ import (
"testing"
"time"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
)
diff --git a/pkg/client/rp/tockenexchange.go b/pkg/client/rp/tockenexchange.go
index aa2cf99..c8ca048 100644
--- a/pkg/client/rp/tockenexchange.go
+++ b/pkg/client/rp/tockenexchange.go
@@ -5,7 +5,7 @@ import (
"golang.org/x/oauth2"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc/grants/tokenexchange"
+ "github.com/zitadel/oidc/v3/pkg/oidc/grants/tokenexchange"
)
// TokenExchangeRP extends the `RelyingParty` interface for the *draft* oauth2 `Token Exchange`
diff --git a/pkg/client/rp/userinfo_example_test.go b/pkg/client/rp/userinfo_example_test.go
index 78e014e..2cc5222 100644
--- a/pkg/client/rp/userinfo_example_test.go
+++ b/pkg/client/rp/userinfo_example_test.go
@@ -4,8 +4,8 @@ import (
"context"
"fmt"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client/rp"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type UserInfo struct {
diff --git a/pkg/client/rp/verifier.go b/pkg/client/rp/verifier.go
index 0088b81..ca59454 100644
--- a/pkg/client/rp/verifier.go
+++ b/pkg/client/rp/verifier.go
@@ -6,8 +6,8 @@ import (
jose "github.com/go-jose/go-jose/v4"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// VerifyTokens implement the Token Response Validation as defined in OIDC specification
diff --git a/pkg/client/rp/verifier_test.go b/pkg/client/rp/verifier_test.go
index 38f5a4a..24d35af 100644
--- a/pkg/client/rp/verifier_test.go
+++ b/pkg/client/rp/verifier_test.go
@@ -5,11 +5,11 @@ import (
"testing"
"time"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
jose "github.com/go-jose/go-jose/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
func TestVerifyTokens(t *testing.T) {
diff --git a/pkg/client/rp/verifier_tokens_example_test.go b/pkg/client/rp/verifier_tokens_example_test.go
index 7ae68d6..892eb23 100644
--- a/pkg/client/rp/verifier_tokens_example_test.go
+++ b/pkg/client/rp/verifier_tokens_example_test.go
@@ -4,9 +4,9 @@ import (
"context"
"fmt"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rp"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/client/rp"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// MyCustomClaims extends the TokenClaims base,
diff --git a/pkg/client/rs/introspect_example_test.go b/pkg/client/rs/introspect_example_test.go
index 1f67d11..eac8be2 100644
--- a/pkg/client/rs/introspect_example_test.go
+++ b/pkg/client/rs/introspect_example_test.go
@@ -4,8 +4,8 @@ import (
"context"
"fmt"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client/rs"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client/rs"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type IntrospectionResponse struct {
diff --git a/pkg/client/rs/resource_server.go b/pkg/client/rs/resource_server.go
index 993796e..962af7e 100644
--- a/pkg/client/rs/resource_server.go
+++ b/pkg/client/rs/resource_server.go
@@ -6,9 +6,9 @@ import (
"net/http"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type ResourceServer interface {
diff --git a/pkg/client/rs/resource_server_test.go b/pkg/client/rs/resource_server_test.go
index afd7441..7a5ced9 100644
--- a/pkg/client/rs/resource_server_test.go
+++ b/pkg/client/rs/resource_server_test.go
@@ -4,9 +4,9 @@ import (
"context"
"testing"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
func TestNewResourceServer(t *testing.T) {
diff --git a/pkg/client/tokenexchange/tokenexchange.go b/pkg/client/tokenexchange/tokenexchange.go
index 9cc1328..61975a4 100644
--- a/pkg/client/tokenexchange/tokenexchange.go
+++ b/pkg/client/tokenexchange/tokenexchange.go
@@ -6,10 +6,10 @@ import (
"net/http"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/go-jose/go-jose/v4"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type TokenExchanger interface {
diff --git a/pkg/crypto/hash.go b/pkg/crypto/hash.go
index 14acdee..ab9f8c1 100644
--- a/pkg/crypto/hash.go
+++ b/pkg/crypto/hash.go
@@ -21,14 +21,6 @@ func GetHashAlgorithm(sigAlgorithm jose.SignatureAlgorithm) (hash.Hash, error) {
return sha512.New384(), nil
case jose.RS512, jose.ES512, jose.PS512:
return sha512.New(), nil
-
- // There is no published spec for this yet, but we have confirmation it will get published.
- // There is consensus here: https://bitbucket.org/openid/connect/issues/1125/_hash-algorithm-for-eddsa-id-tokens
- // Currently Go and go-jose only supports the ed25519 curve key for EdDSA, so we can safely assume sha512 here.
- // It is unlikely ed448 will ever be supported: https://github.com/golang/go/issues/29390
- case jose.EdDSA:
- return sha512.New(), nil
-
default:
return nil, fmt.Errorf("%w: %q", ErrUnsupportedAlgorithm, sigAlgorithm)
}
diff --git a/pkg/crypto/key.go b/pkg/crypto/key.go
index 12bca28..79e2046 100644
--- a/pkg/crypto/key.go
+++ b/pkg/crypto/key.go
@@ -1,45 +1,22 @@
package crypto
import (
- "crypto"
- "crypto/ecdsa"
- "crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
-
- "github.com/go-jose/go-jose/v4"
)
-var (
- ErrPEMDecode = errors.New("PEM decode failed")
- ErrUnsupportedFormat = errors.New("key is neither in PKCS#1 nor PKCS#8 format")
- ErrUnsupportedPrivateKey = errors.New("unsupported key type, must be RSA, ECDSA or ED25519 private key")
-)
-
-func BytesToPrivateKey(b []byte) (crypto.PublicKey, jose.SignatureAlgorithm, error) {
+func BytesToPrivateKey(b []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode(b)
if block == nil {
- return nil, "", ErrPEMDecode
+ return nil, errors.New("PEM decode failed")
}
- privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
- if err == nil {
- return privateKey, jose.RS256, nil
- }
- key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
+ key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
- return nil, "", ErrUnsupportedFormat
- }
- switch privateKey := key.(type) {
- case *rsa.PrivateKey:
- return privateKey, jose.RS256, nil
- case ed25519.PrivateKey:
- return privateKey, jose.EdDSA, nil
- case *ecdsa.PrivateKey:
- return privateKey, jose.ES256, nil
- default:
- return nil, "", ErrUnsupportedPrivateKey
+ return nil, err
}
+
+ return key, nil
}
diff --git a/pkg/crypto/key_test.go b/pkg/crypto/key_test.go
index a6fa493..23ebdc0 100644
--- a/pkg/crypto/key_test.go
+++ b/pkg/crypto/key_test.go
@@ -1,64 +1,21 @@
package crypto_test
import (
- "crypto"
- "crypto/ecdsa"
- "crypto/ed25519"
- "crypto/rsa"
"testing"
- "github.com/go-jose/go-jose/v4"
"github.com/stretchr/testify/assert"
- zcrypto "git.christmann.info/LARA/zitadel-oidc/v3/pkg/crypto"
+ "github.com/zitadel/oidc/v3/pkg/crypto"
)
-func TestBytesToPrivateKey(t *testing.T) {
- type args struct {
- key []byte
- }
- type want struct {
- key crypto.Signer
- algorithm jose.SignatureAlgorithm
- err error
- }
- tests := []struct {
- name string
- args args
- want want
- }{
- {
- name: "PEMDecodeError",
- args: args{
- key: []byte("The non-PEM sequence"),
- },
- want: want{
- err: zcrypto.ErrPEMDecode,
- },
- },
- {
- name: "PKCS#1 RSA",
- args: args{
- key: []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIBOgIBAAJBAKj34GkxFhD90vcNLYLInFEX6Ppy1tPf9Cnzj4p4WGeKLs1Pt8Qu
-KUpRKfFLfRYC9AIKjbJTWit+CqvjWYzvQwECAwEAAQJAIJLixBy2qpFoS4DSmoEm
-o3qGy0t6z09AIJtH+5OeRV1be+N4cDYJKffGzDa88vQENZiRm0GRq6a+HPGQMd2k
-TQIhAKMSvzIBnni7ot/OSie2TmJLY4SwTQAevXysE2RbFDYdAiEBCUEaRQnMnbp7
-9mxDXDf6AU0cN/RPBjb9qSHDcWZHGzUCIG2Es59z8ugGrDY+pxLQnwfotadxd+Uy
-v/Ow5T0q5gIJAiEAyS4RaI9YG8EWx/2w0T67ZUVAw8eOMB6BIUg0Xcu+3okCIBOs
-/5OiPgoTdSy7bcF9IGpSE8ZgGKzgYQVZeN97YE00
------END RSA PRIVATE KEY-----`),
- },
- want: want{
- key: &rsa.PrivateKey{},
- algorithm: jose.RS256,
- err: nil,
- },
- },
- {
- name: "PKCS#8 RSA",
- args: args{
- key: []byte(`-----BEGIN PRIVATE KEY-----
+func TestBytesToPrivateKey(tt *testing.T) {
+ tt.Run("PEMDecodeError", func(t *testing.T) {
+ _, err := crypto.BytesToPrivateKey([]byte("The non-PEM sequence"))
+ assert.EqualError(t, err, "PEM decode failed")
+ })
+
+ tt.Run("InvalidKeyFormat", func(t *testing.T) {
+ _, err := crypto.BytesToPrivateKey([]byte(`-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCfaDB7pK/fmP/I
7IusSK8lTCBnPZghqIbVLt2QHYAMoEF1CaF4F4rxo2vl1Mt8gwsq4T3osQFZMvnL
YHb7KNyUoJgTjLxJQADv2u4Q3U38heAzK5Tp4ry4MCnuyJIqAPK1GiruwEq4zQrx
@@ -85,50 +42,21 @@ srJnjF0H8oKmAY6hw+1Tm/n/b08p+RyL48TgVSE2vhUCgYA3BWpkD4PlCcn/FZsq
OrLFyFXI6jIaxskFtsRW1IxxIlAdZmxfB26P/2gx6VjLdxJI/RRPkJyEN2dP7CbR
BDjb565dy1O9D6+UrY70Iuwjz+OcALRBBGTaiF2pLn6IhSzNI2sy/tXX8q8dBlg9
OFCrqT/emes3KytTPfa5NZtYeQ==
------END PRIVATE KEY-----`),
- },
- want: want{
- key: &rsa.PrivateKey{},
- algorithm: jose.RS256,
- err: nil,
- },
- },
- {
- name: "PKCS#8 ECDSA",
- args: args{
- key: []byte(`-----BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwwOZSU4GlP7ps/Wp
-V6o0qRwxultdfYo/uUuj48QZjSuhRANCAATMiI2Han+ABKmrk5CNlxRAGC61w4d3
-G4TAeuBpyzqJ7x/6NjCxoQzJzZHtNjIfjVATI59XFZWF59GhtSZbShAr
------END PRIVATE KEY-----`),
- },
- want: want{
- key: &ecdsa.PrivateKey{},
- algorithm: jose.ES256,
- err: nil,
- },
- },
- {
- name: "PKCS#8 ED25519",
- args: args{
- key: []byte(`-----BEGIN PRIVATE KEY-----
-MC4CAQAwBQYDK2VwBCIEIHu6ZtDsjjauMasBxnS9Fg87UJwKfcT/oiq6S0ktbky8
------END PRIVATE KEY-----`),
- },
- want: want{
- key: ed25519.PrivateKey{},
- algorithm: jose.EdDSA,
- err: nil,
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- key, algorithm, err := zcrypto.BytesToPrivateKey(tt.args.key)
- assert.IsType(t, tt.want.key, key)
- assert.Equal(t, tt.want.algorithm, algorithm)
- assert.ErrorIs(t, tt.want.err, err)
- })
+-----END PRIVATE KEY-----`))
+ assert.EqualError(t, err, "x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)")
+ })
- }
+ tt.Run("Ok", func(t *testing.T) {
+ key, err := crypto.BytesToPrivateKey([]byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBAKj34GkxFhD90vcNLYLInFEX6Ppy1tPf9Cnzj4p4WGeKLs1Pt8Qu
+KUpRKfFLfRYC9AIKjbJTWit+CqvjWYzvQwECAwEAAQJAIJLixBy2qpFoS4DSmoEm
+o3qGy0t6z09AIJtH+5OeRV1be+N4cDYJKffGzDa88vQENZiRm0GRq6a+HPGQMd2k
+TQIhAKMSvzIBnni7ot/OSie2TmJLY4SwTQAevXysE2RbFDYdAiEBCUEaRQnMnbp7
+9mxDXDf6AU0cN/RPBjb9qSHDcWZHGzUCIG2Es59z8ugGrDY+pxLQnwfotadxd+Uy
+v/Ow5T0q5gIJAiEAyS4RaI9YG8EWx/2w0T67ZUVAw8eOMB6BIUg0Xcu+3okCIBOs
+/5OiPgoTdSy7bcF9IGpSE8ZgGKzgYQVZeN97YE00
+-----END RSA PRIVATE KEY-----`))
+ assert.NoError(t, err)
+ assert.NotNil(t, key)
+ })
}
diff --git a/pkg/http/http.go b/pkg/http/http.go
index aa0ff6f..33c5f15 100644
--- a/pkg/http/http.go
+++ b/pkg/http/http.go
@@ -11,7 +11,7 @@ import (
"strings"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
var DefaultHTTPClient = &http.Client{
diff --git a/pkg/oidc/code_challenge.go b/pkg/oidc/code_challenge.go
index 0c593df..3296362 100644
--- a/pkg/oidc/code_challenge.go
+++ b/pkg/oidc/code_challenge.go
@@ -3,7 +3,7 @@ package oidc
import (
"crypto/sha256"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/crypto"
+ "github.com/zitadel/oidc/v3/pkg/crypto"
)
const (
diff --git a/pkg/oidc/discovery.go b/pkg/oidc/discovery.go
index 62288d1..14fce5e 100644
--- a/pkg/oidc/discovery.go
+++ b/pkg/oidc/discovery.go
@@ -145,14 +145,6 @@ type DiscoveryConfiguration struct {
// OPTermsOfServiceURI is a URL the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service.
OPTermsOfServiceURI string `json:"op_tos_uri,omitempty"`
-
- // BackChannelLogoutSupported specifies whether the OP supports back-channel logout (https://openid.net/specs/openid-connect-backchannel-1_0.html),
- // with true indicating support. If omitted, the default value is false.
- BackChannelLogoutSupported bool `json:"backchannel_logout_supported,omitempty"`
-
- // BackChannelLogoutSessionSupported specifies whether the OP can pass a sid (session ID) Claim in the Logout Token to identify the RP session with the OP.
- // If supported, the sid Claim is also included in ID Tokens issued by the OP. If omitted, the default value is false.
- BackChannelLogoutSessionSupported bool `json:"backchannel_logout_session_supported,omitempty"`
}
type AuthMethod string
diff --git a/pkg/oidc/error.go b/pkg/oidc/error.go
index d93cf44..2f0572d 100644
--- a/pkg/oidc/error.go
+++ b/pkg/oidc/error.go
@@ -1,7 +1,6 @@
package oidc
import (
- "encoding/json"
"errors"
"fmt"
"log/slog"
@@ -133,28 +132,7 @@ type Error struct {
ErrorType errorType `json:"error" schema:"error"`
Description string `json:"error_description,omitempty" schema:"error_description,omitempty"`
State string `json:"state,omitempty" schema:"state,omitempty"`
- SessionState string `json:"session_state,omitempty" schema:"session_state,omitempty"`
redirectDisabled bool `schema:"-"`
- returnParent bool `schema:"-"`
-}
-
-func (e *Error) MarshalJSON() ([]byte, error) {
- m := struct {
- Error errorType `json:"error"`
- ErrorDescription string `json:"error_description,omitempty"`
- State string `json:"state,omitempty"`
- SessionState string `json:"session_state,omitempty"`
- Parent string `json:"parent,omitempty"`
- }{
- Error: e.ErrorType,
- ErrorDescription: e.Description,
- State: e.State,
- SessionState: e.SessionState,
- }
- if e.returnParent {
- m.Parent = e.Parent.Error()
- }
- return json.Marshal(m)
}
func (e *Error) Error() string {
@@ -179,8 +157,7 @@ func (e *Error) Is(target error) bool {
}
return e.ErrorType == t.ErrorType &&
(e.Description == t.Description || t.Description == "") &&
- (e.State == t.State || t.State == "") &&
- (e.SessionState == t.SessionState || t.SessionState == "")
+ (e.State == t.State || t.State == "")
}
func (e *Error) WithParent(err error) *Error {
@@ -188,18 +165,6 @@ func (e *Error) WithParent(err error) *Error {
return e
}
-// WithReturnParentToClient allows returning the set parent error to the HTTP client.
-// Currently it only supports setting the parent inside JSON responses, not redirect URLs.
-// As Go errors don't unmarshal well, only the marshaller is implemented for the moment.
-//
-// Warning: parent errors may contain sensitive data or unwanted details about the server status.
-// Also, the `parent` field is not a standard error field and might confuse certain clients
-// that require fully compliant responses.
-func (e *Error) WithReturnParentToClient(b bool) *Error {
- e.returnParent = b
- return e
-}
-
func (e *Error) WithDescription(desc string, args ...any) *Error {
e.Description = fmt.Sprintf(desc, args...)
return e
@@ -246,9 +211,6 @@ func (e *Error) LogValue() slog.Value {
if e.State != "" {
attrs = append(attrs, slog.String("state", e.State))
}
- if e.SessionState != "" {
- attrs = append(attrs, slog.String("session_state", e.SessionState))
- }
if e.redirectDisabled {
attrs = append(attrs, slog.Bool("redirect_disabled", e.redirectDisabled))
}
diff --git a/pkg/oidc/error_test.go b/pkg/oidc/error_test.go
index 40d30b1..2eeb4e6 100644
--- a/pkg/oidc/error_test.go
+++ b/pkg/oidc/error_test.go
@@ -1,14 +1,11 @@
package oidc
import (
- "encoding/json"
- "errors"
"io"
"log/slog"
"testing"
"github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
)
func TestDefaultToServerError(t *testing.T) {
@@ -154,39 +151,3 @@ func TestError_LogValue(t *testing.T) {
})
}
}
-
-func TestError_MarshalJSON(t *testing.T) {
- tests := []struct {
- name string
- e *Error
- want string
- }{
- {
- name: "simple error",
- e: ErrAccessDenied(),
- want: `{"error":"access_denied","error_description":"The authorization request was denied."}`,
- },
- {
- name: "with description",
- e: ErrAccessDenied().WithDescription("oops"),
- want: `{"error":"access_denied","error_description":"oops"}`,
- },
- {
- name: "with parent",
- e: ErrServerError().WithParent(errors.New("oops")),
- want: `{"error":"server_error"}`,
- },
- {
- name: "with return parent",
- e: ErrServerError().WithParent(errors.New("oops")).WithReturnParentToClient(true),
- want: `{"error":"server_error","parent":"oops"}`,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := json.Marshal(tt.e)
- require.NoError(t, err)
- assert.JSONEq(t, tt.want, string(got))
- })
- }
-}
diff --git a/pkg/oidc/keyset.go b/pkg/oidc/keyset.go
index a8b89b0..833878d 100644
--- a/pkg/oidc/keyset.go
+++ b/pkg/oidc/keyset.go
@@ -6,7 +6,6 @@ import (
"crypto/ed25519"
"crypto/rsa"
"errors"
- "strings"
jose "github.com/go-jose/go-jose/v4"
)
@@ -93,17 +92,17 @@ func FindMatchingKey(keyID, use, expectedAlg string, keys ...jose.JSONWebKey) (k
}
func algToKeyType(key any, alg string) bool {
- if strings.HasPrefix(alg, "RS") || strings.HasPrefix(alg, "PS") {
+ switch alg[0] {
+ case 'R', 'P':
_, ok := key.(*rsa.PublicKey)
return ok
- }
- if strings.HasPrefix(alg, "ES") {
+ case 'E':
_, ok := key.(*ecdsa.PublicKey)
return ok
- }
- if alg == string(jose.EdDSA) {
- _, ok := key.(ed25519.PublicKey)
+ case 'O':
+ _, ok := key.(*ed25519.PublicKey)
return ok
+ default:
+ return false
}
- return false
}
diff --git a/pkg/oidc/session.go b/pkg/oidc/session.go
index 39f9f08..b470d1e 100644
--- a/pkg/oidc/session.go
+++ b/pkg/oidc/session.go
@@ -1,12 +1,10 @@
package oidc
// EndSessionRequest for the RP-Initiated Logout according to:
-// https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout
+//https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout
type EndSessionRequest struct {
- IdTokenHint string `schema:"id_token_hint"`
- LogoutHint string `schema:"logout_hint"`
- ClientID string `schema:"client_id"`
- PostLogoutRedirectURI string `schema:"post_logout_redirect_uri"`
- State string `schema:"state"`
- UILocales Locales `schema:"ui_locales"`
+ IdTokenHint string `schema:"id_token_hint"`
+ ClientID string `schema:"client_id"`
+ PostLogoutRedirectURI string `schema:"post_logout_redirect_uri"`
+ State string `schema:"state"`
}
diff --git a/pkg/oidc/token.go b/pkg/oidc/token.go
index 4b43dcb..8d2880c 100644
--- a/pkg/oidc/token.go
+++ b/pkg/oidc/token.go
@@ -9,8 +9,7 @@ import (
"golang.org/x/oauth2"
"github.com/muhlemmer/gu"
-
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/crypto"
+ "github.com/zitadel/oidc/v3/pkg/crypto"
)
const (
@@ -117,7 +116,6 @@ func NewAccessTokenClaims(issuer, subject string, audience []string, expiration
Expiration: FromTime(expiration),
IssuedAt: FromTime(now),
NotBefore: FromTime(now),
- ClientID: clientID,
JWTID: jwtid,
},
}
@@ -230,13 +228,12 @@ func (c *ActorClaims) UnmarshalJSON(data []byte) error {
}
type AccessTokenResponse struct {
- AccessToken string `json:"access_token,omitempty" schema:"access_token,omitempty"`
- TokenType string `json:"token_type,omitempty" schema:"token_type,omitempty"`
- RefreshToken string `json:"refresh_token,omitempty" schema:"refresh_token,omitempty"`
- ExpiresIn uint64 `json:"expires_in,omitempty" schema:"expires_in,omitempty"`
- IDToken string `json:"id_token,omitempty" schema:"id_token,omitempty"`
- State string `json:"state,omitempty" schema:"state,omitempty"`
- Scope SpaceDelimitedArray `json:"scope,omitempty" schema:"scope,omitempty"`
+ AccessToken string `json:"access_token,omitempty" schema:"access_token,omitempty"`
+ TokenType string `json:"token_type,omitempty" schema:"token_type,omitempty"`
+ RefreshToken string `json:"refresh_token,omitempty" schema:"refresh_token,omitempty"`
+ ExpiresIn uint64 `json:"expires_in,omitempty" schema:"expires_in,omitempty"`
+ IDToken string `json:"id_token,omitempty" schema:"id_token,omitempty"`
+ State string `json:"state,omitempty" schema:"state,omitempty"`
}
type JWTProfileAssertionClaims struct {
@@ -347,12 +344,12 @@ func AppendClientIDToAudience(clientID string, audience []string) []string {
}
func GenerateJWTProfileToken(assertion *JWTProfileAssertionClaims) (string, error) {
- privateKey, algorithm, err := crypto.BytesToPrivateKey(assertion.PrivateKey)
+ privateKey, err := crypto.BytesToPrivateKey(assertion.PrivateKey)
if err != nil {
return "", err
}
key := jose.SigningKey{
- Algorithm: algorithm,
+ Algorithm: jose.RS256,
Key: &jose.JSONWebKey{Key: privateKey, KeyID: assertion.PrivateKeyID},
}
signer, err := jose.NewSigner(key, &jose.SignerOptions{})
@@ -383,40 +380,3 @@ type TokenExchangeResponse struct {
// if the requested_token_type was Access Token and scope contained openid.
IDToken string `json:"id_token,omitempty"`
}
-
-type LogoutTokenClaims struct {
- Issuer string `json:"iss,omitempty"`
- Subject string `json:"sub,omitempty"`
- Audience Audience `json:"aud,omitempty"`
- IssuedAt Time `json:"iat,omitempty"`
- Expiration Time `json:"exp,omitempty"`
- JWTID string `json:"jti,omitempty"`
- Events map[string]any `json:"events,omitempty"`
- SessionID string `json:"sid,omitempty"`
- Claims map[string]any `json:"-"`
-}
-
-type ltcAlias LogoutTokenClaims
-
-func (i *LogoutTokenClaims) MarshalJSON() ([]byte, error) {
- return mergeAndMarshalClaims((*ltcAlias)(i), i.Claims)
-}
-
-func (i *LogoutTokenClaims) UnmarshalJSON(data []byte) error {
- return unmarshalJSONMulti(data, (*ltcAlias)(i), &i.Claims)
-}
-
-func NewLogoutTokenClaims(issuer, subject string, audience Audience, expiration time.Time, jwtID, sessionID string, skew time.Duration) *LogoutTokenClaims {
- return &LogoutTokenClaims{
- Issuer: issuer,
- Subject: subject,
- Audience: audience,
- IssuedAt: FromTime(time.Now().Add(-skew)),
- Expiration: FromTime(expiration),
- JWTID: jwtID,
- Events: map[string]any{
- "http://schemas.openid.net/event/backchannel-logout": struct{}{},
- },
- SessionID: sessionID,
- }
-}
diff --git a/pkg/oidc/token_request.go b/pkg/oidc/token_request.go
index dadb205..f3b2ec4 100644
--- a/pkg/oidc/token_request.go
+++ b/pkg/oidc/token_request.go
@@ -72,10 +72,10 @@ type AccessTokenRequest struct {
Code string `schema:"code"`
RedirectURI string `schema:"redirect_uri"`
ClientID string `schema:"client_id"`
- ClientSecret string `schema:"client_secret,omitempty"`
- CodeVerifier string `schema:"code_verifier,omitempty"`
- ClientAssertion string `schema:"client_assertion,omitempty"`
- ClientAssertionType string `schema:"client_assertion_type,omitempty"`
+ ClientSecret string `schema:"client_secret"`
+ CodeVerifier string `schema:"code_verifier"`
+ ClientAssertion string `schema:"client_assertion"`
+ ClientAssertionType string `schema:"client_assertion_type"`
}
func (a *AccessTokenRequest) GrantType() GrantType {
diff --git a/pkg/oidc/token_test.go b/pkg/oidc/token_test.go
index 621cdbc..ccc3467 100644
--- a/pkg/oidc/token_test.go
+++ b/pkg/oidc/token_test.go
@@ -145,7 +145,6 @@ func TestNewAccessTokenClaims(t *testing.T) {
Subject: "hello@me.com",
Audience: Audience{"foo"},
Expiration: 12345,
- ClientID: "foo",
JWTID: "900",
},
}
@@ -242,39 +241,3 @@ func TestIDTokenClaims_GetUserInfo(t *testing.T) {
got := idTokenData.GetUserInfo()
assert.Equal(t, want, got)
}
-
-func TestNewLogoutTokenClaims(t *testing.T) {
- want := &LogoutTokenClaims{
- Issuer: "zitadel",
- Subject: "hello@me.com",
- Audience: Audience{"foo", "just@me.com"},
- Expiration: 12345,
- JWTID: "jwtID",
- Events: map[string]any{
- "http://schemas.openid.net/event/backchannel-logout": struct{}{},
- },
- SessionID: "sessionID",
- Claims: nil,
- }
-
- got := NewLogoutTokenClaims(
- want.Issuer,
- want.Subject,
- want.Audience,
- want.Expiration.AsTime(),
- want.JWTID,
- want.SessionID,
- 1*time.Second,
- )
-
- // test if the dynamic timestamp is around now,
- // allowing for a delta of 1, just in case we flip on
- // either side of a second boundry.
- nowMinusSkew := NowTime() - 1
- assert.InDelta(t, int64(nowMinusSkew), int64(got.IssuedAt), 1)
-
- // Make equal not fail on dynamic timestamp
- got.IssuedAt = 0
-
- assert.Equal(t, want, got)
-}
diff --git a/pkg/oidc/types.go b/pkg/oidc/types.go
index 5d063b1..e7292e6 100644
--- a/pkg/oidc/types.go
+++ b/pkg/oidc/types.go
@@ -35,17 +35,6 @@ func (a *Audience) UnmarshalJSON(text []byte) error {
return nil
}
-func (a *Audience) MarshalJSON() ([]byte, error) {
- len := len(*a)
- if len > 1 {
- return json.Marshal(*a)
- } else if len == 1 {
- return json.Marshal((*a)[0])
- }
-
- return nil, errors.New("aud is empty")
-}
-
type Display string
func (d *Display) UnmarshalText(text []byte) error {
@@ -93,9 +82,6 @@ func (l *Locale) MarshalJSON() ([]byte, error) {
// to an empty value (language "und") and no error will be returned.
// This state can be checked with the `l.Tag().IsRoot()` method.
func (l *Locale) UnmarshalJSON(data []byte) error {
- if len(data) == 0 || string(data) == "\"\"" {
- return nil
- }
err := json.Unmarshal(data, &l.tag)
if err == nil {
return nil
@@ -126,14 +112,6 @@ func ParseLocales(locales []string) Locales {
return out
}
-func (l Locales) String() string {
- tags := make([]string, len(l))
- for i, tag := range l {
- tags[i] = tag.String()
- }
- return strings.Join(tags, " ")
-}
-
// UnmarshalText implements the [encoding.TextUnmarshaler] interface.
// It decodes an unquoted space seperated string into Locales.
// Undefined language tags in the input are ignored and ommited from
@@ -250,9 +228,6 @@ func NewEncoder() *schema.Encoder {
e.RegisterEncoder(SpaceDelimitedArray{}, func(value reflect.Value) string {
return value.Interface().(SpaceDelimitedArray).String()
})
- e.RegisterEncoder(Locales{}, func(value reflect.Value) string {
- return value.Interface().(Locales).String()
- })
return e
}
diff --git a/pkg/oidc/types_test.go b/pkg/oidc/types_test.go
index 53a9779..df93a73 100644
--- a/pkg/oidc/types_test.go
+++ b/pkg/oidc/types_test.go
@@ -217,30 +217,6 @@ func TestLocale_UnmarshalJSON(t *testing.T) {
want dst
wantErr bool
}{
- {
- name: "value not present",
- input: `{}`,
- wantErr: false,
- want: dst{
- Locale: nil,
- },
- },
- {
- name: "null",
- input: `{"locale": null}`,
- wantErr: false,
- want: dst{
- Locale: nil,
- },
- },
- {
- name: "empty, ignored",
- input: `{"locale": ""}`,
- wantErr: false,
- want: dst{
- Locale: &Locale{},
- },
- },
{
name: "afrikaans, ok",
input: `{"locale": "af"}`,
@@ -261,17 +237,16 @@ func TestLocale_UnmarshalJSON(t *testing.T) {
wantErr: true,
},
}
+
for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- var got dst
- err := json.Unmarshal([]byte(tt.input), &got)
- if tt.wantErr {
- require.Error(t, err)
- return
- }
- require.NoError(t, err)
- assert.Equal(t, tt.want, got)
- })
+ var got dst
+ err := json.Unmarshal([]byte(tt.input), &got)
+ if tt.wantErr {
+ require.Error(t, err)
+ return
+ }
+ require.NoError(t, err)
+ assert.Equal(t, tt.want, got)
}
}
diff --git a/pkg/oidc/verifier.go b/pkg/oidc/verifier.go
index d5e0213..410b383 100644
--- a/pkg/oidc/verifier.go
+++ b/pkg/oidc/verifier.go
@@ -7,11 +7,12 @@ import (
"encoding/json"
"errors"
"fmt"
- "slices"
"strings"
"time"
jose "github.com/go-jose/go-jose/v4"
+
+ str "github.com/zitadel/oidc/v3/pkg/strings"
)
type Claims interface {
@@ -40,7 +41,6 @@ type IDClaims interface {
var (
ErrParse = errors.New("parsing of request failed")
ErrIssuerInvalid = errors.New("issuer does not match")
- ErrDiscoveryFailed = errors.New("OpenID Provider Configuration Discovery has failed")
ErrSubjectMissing = errors.New("subject missing")
ErrAudience = errors.New("audience is not valid")
ErrAzpMissing = errors.New("authorized party is not set. If Token is valid for multiple audiences, azp must not be empty")
@@ -83,7 +83,7 @@ type ACRVerifier func(string) error
// if none of the provided values matches the acr claim
func DefaultACRVerifier(possibleValues []string) ACRVerifier {
return func(acr string) error {
- if !slices.Contains(possibleValues, acr) {
+ if !str.Contains(possibleValues, acr) {
return fmt.Errorf("expected one of: %v, got: %q", possibleValues, acr)
}
return nil
@@ -122,7 +122,7 @@ func CheckIssuer(claims Claims, issuer string) error {
}
func CheckAudience(claims Claims, clientID string) error {
- if !slices.Contains(claims.GetAudience(), clientID) {
+ if !str.Contains(claims.GetAudience(), clientID) {
return fmt.Errorf("%w: Audience must contain client_id %q", ErrAudience, clientID)
}
@@ -186,7 +186,7 @@ func toJoseSignatureAlgorithms(algorithms []string) []jose.SignatureAlgorithm {
out[i] = jose.SignatureAlgorithm(algorithms[i])
}
if len(out) == 0 {
- out = append(out, jose.RS256, jose.ES256, jose.PS256)
+ out = append(out, jose.RS256)
}
return out
}
diff --git a/pkg/oidc/verifier_parse_test.go b/pkg/oidc/verifier_parse_test.go
index 9cf5c1e..105650f 100644
--- a/pkg/oidc/verifier_parse_test.go
+++ b/pkg/oidc/verifier_parse_test.go
@@ -5,10 +5,10 @@ import (
"encoding/json"
"testing"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
func TestParseToken(t *testing.T) {
diff --git a/pkg/op/auth_request.go b/pkg/op/auth_request.go
index b1434cc..923b9a7 100644
--- a/pkg/op/auth_request.go
+++ b/pkg/op/auth_request.go
@@ -11,13 +11,13 @@ import (
"net"
"net/http"
"net/url"
- "slices"
"strings"
"time"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/bmatcuk/doublestar/v4"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ str "github.com/zitadel/oidc/v3/pkg/strings"
)
type AuthRequest interface {
@@ -38,13 +38,6 @@ type AuthRequest interface {
Done() bool
}
-// AuthRequestSessionState should be implemented if [OpenID Connect Session Management](https://openid.net/specs/openid-connect-session-1_0.html) is supported
-type AuthRequestSessionState interface {
- // GetSessionState returns session_state.
- // session_state is related to OpenID Connect Session Management.
- GetSessionState() string
-}
-
type Authorizer interface {
Storage() Storage
Decoder() httphelper.Decoder
@@ -62,12 +55,6 @@ type AuthorizeValidator interface {
ValidateAuthRequest(context.Context, *oidc.AuthRequest, Storage, *IDTokenHintVerifier) (string, error)
}
-type CodeResponseType struct {
- Code string `schema:"code"`
- State string `schema:"state,omitempty"`
- SessionState string `schema:"session_state,omitempty"`
-}
-
func authorizeHandler(authorizer Authorizer) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
Authorize(w, r, authorizer)
@@ -95,29 +82,21 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
if authReq.RequestParam != "" && authorizer.RequestObjectSupported() {
err = ParseRequestObject(ctx, authReq, authorizer.Storage(), IssuerFromContext(ctx))
if err != nil {
- AuthRequestError(w, r, nil, err, authorizer)
+ AuthRequestError(w, r, authReq, err, authorizer)
return
}
}
if authReq.ClientID == "" {
- AuthRequestError(w, r, nil, fmt.Errorf("auth request is missing client_id"), authorizer)
+ AuthRequestError(w, r, authReq, fmt.Errorf("auth request is missing client_id"), authorizer)
return
}
if authReq.RedirectURI == "" {
- AuthRequestError(w, r, nil, fmt.Errorf("auth request is missing redirect_uri"), authorizer)
+ AuthRequestError(w, r, authReq, fmt.Errorf("auth request is missing redirect_uri"), authorizer)
return
}
-
- var client Client
- validation := func(ctx context.Context, authReq *oidc.AuthRequest, storage Storage, verifier *IDTokenHintVerifier) (sub string, err error) {
- client, err = authorizer.Storage().GetClientByClientID(ctx, authReq.ClientID)
- if err != nil {
- return "", oidc.ErrInvalidRequestRedirectURI().WithDescription("unable to retrieve client by id").WithParent(err)
- }
- return ValidateAuthRequestClient(ctx, authReq, client, verifier)
- }
- if validator, ok := authorizer.(AuthorizeValidator); ok {
- validation = validator.ValidateAuthRequest
+ validation := ValidateAuthRequest
+ if validater, ok := authorizer.(AuthorizeValidator); ok {
+ validation = validater.ValidateAuthRequest
}
userID, err := validation(ctx, authReq, authorizer.Storage(), authorizer.IDTokenHintVerifier(ctx))
if err != nil {
@@ -133,6 +112,11 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
AuthRequestError(w, r, authReq, oidc.DefaultToServerError(err, "unable to save auth request"), authorizer)
return
}
+ client, err := authorizer.Storage().GetClientByClientID(ctx, req.GetClientID())
+ if err != nil {
+ AuthRequestError(w, r, req, oidc.DefaultToServerError(err, "unable to retrieve client by id"), authorizer)
+ return
+ }
RedirectToLogin(req.GetID(), client, w, r)
}
@@ -168,7 +152,7 @@ func ParseRequestObject(ctx context.Context, authReq *oidc.AuthRequest, storage
if requestObject.Issuer != requestObject.ClientID {
return oidc.ErrInvalidRequest().WithDescription("missing or wrong issuer in request")
}
- if !slices.Contains(requestObject.Audience, issuer) {
+ if !str.Contains(requestObject.Audience, issuer) {
return oidc.ErrInvalidRequest().WithDescription("issuer missing in audience")
}
keySet := &jwtProfileKeySet{storage: storage, clientID: requestObject.Issuer}
@@ -182,7 +166,7 @@ func ParseRequestObject(ctx context.Context, authReq *oidc.AuthRequest, storage
// CopyRequestObjectToAuthRequest overwrites present values from the Request Object into the auth request
// and clears the `RequestParam` of the auth request
func CopyRequestObjectToAuthRequest(authReq *oidc.AuthRequest, requestObject *oidc.RequestObject) {
- if slices.Contains(authReq.Scopes, oidc.ScopeOpenID) && len(requestObject.Scopes) > 0 {
+ if str.Contains(authReq.Scopes, oidc.ScopeOpenID) && len(requestObject.Scopes) > 0 {
authReq.Scopes = requestObject.Scopes
}
if requestObject.RedirectURI != "" {
@@ -227,37 +211,26 @@ func CopyRequestObjectToAuthRequest(authReq *oidc.AuthRequest, requestObject *oi
authReq.RequestParam = ""
}
-// ValidateAuthRequest validates the authorize parameters and returns the userID of the id_token_hint if passed.
-//
-// Deprecated: Use [ValidateAuthRequestClient] to prevent querying for the Client twice.
+// ValidateAuthRequest validates the authorize parameters and returns the userID of the id_token_hint if passed
func ValidateAuthRequest(ctx context.Context, authReq *oidc.AuthRequest, storage Storage, verifier *IDTokenHintVerifier) (sub string, err error) {
ctx, span := tracer.Start(ctx, "ValidateAuthRequest")
defer span.End()
- client, err := storage.GetClientByClientID(ctx, authReq.ClientID)
- if err != nil {
- return "", oidc.ErrInvalidRequestRedirectURI().WithDescription("unable to retrieve client by id").WithParent(err)
- }
- return ValidateAuthRequestClient(ctx, authReq, client, verifier)
-}
-
-// ValidateAuthRequestClient validates the Auth request against the passed client.
-// If id_token_hint is part of the request, the subject of the token is returned.
-func ValidateAuthRequestClient(ctx context.Context, authReq *oidc.AuthRequest, client Client, verifier *IDTokenHintVerifier) (sub string, err error) {
- ctx, span := tracer.Start(ctx, "ValidateAuthRequestClient")
- defer span.End()
-
- if err := ValidateAuthReqRedirectURI(client, authReq.RedirectURI, authReq.ResponseType); err != nil {
- return "", err
- }
authReq.MaxAge, err = ValidateAuthReqPrompt(authReq.Prompt, authReq.MaxAge)
if err != nil {
return "", err
}
+ client, err := storage.GetClientByClientID(ctx, authReq.ClientID)
+ if err != nil {
+ return "", oidc.DefaultToServerError(err, "unable to retrieve client by id")
+ }
authReq.Scopes, err = ValidateAuthReqScopes(client, authReq.Scopes)
if err != nil {
return "", err
}
+ if err := ValidateAuthReqRedirectURI(client, authReq.RedirectURI, authReq.ResponseType); err != nil {
+ return "", err
+ }
if err := ValidateAuthReqResponseType(client, authReq.ResponseType); err != nil {
return "", err
}
@@ -277,30 +250,44 @@ func ValidateAuthReqPrompt(prompts []string, maxAge *uint) (_ *uint, err error)
return maxAge, nil
}
-// ValidateAuthReqScopes validates the passed scopes and deletes any unsupported scopes.
-// An error is returned if scopes is empty.
+// ValidateAuthReqScopes validates the passed scopes
func ValidateAuthReqScopes(client Client, scopes []string) ([]string, error) {
if len(scopes) == 0 {
return nil, oidc.ErrInvalidRequest().
WithDescription("The scope of your request is missing. Please ensure some scopes are requested. " +
"If you have any questions, you may contact the administrator of the application.")
}
- scopes = slices.DeleteFunc(scopes, func(scope string) bool {
- return !(scope == oidc.ScopeOpenID ||
- scope == oidc.ScopeProfile ||
+ openID := false
+ for i := len(scopes) - 1; i >= 0; i-- {
+ scope := scopes[i]
+ if scope == oidc.ScopeOpenID {
+ openID = true
+ continue
+ }
+ if !(scope == oidc.ScopeProfile ||
scope == oidc.ScopeEmail ||
scope == oidc.ScopePhone ||
scope == oidc.ScopeAddress ||
scope == oidc.ScopeOfflineAccess) &&
- !client.IsScopeAllowed(scope)
- })
+ !client.IsScopeAllowed(scope) {
+ scopes[i] = scopes[len(scopes)-1]
+ scopes[len(scopes)-1] = ""
+ scopes = scopes[:len(scopes)-1]
+ }
+ }
+ if !openID {
+ return nil, oidc.ErrInvalidScope().WithDescription("The scope openid is missing in your request. " +
+ "Please ensure the scope openid is added to the request. " +
+ "If you have any questions, you may contact the administrator of the application.")
+ }
+
return scopes, nil
}
// checkURIAgainstRedirects just checks aginst the valid redirect URIs and ignores
// other factors.
func checkURIAgainstRedirects(client Client, uri string) error {
- if slices.Contains(client.RedirectURIs(), uri) {
+ if str.Contains(client.RedirectURIs(), uri) {
return nil
}
if globClient, ok := client.(HasRedirectGlobs); ok {
@@ -325,12 +312,12 @@ func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.Res
return oidc.ErrInvalidRequestRedirectURI().WithDescription("The redirect_uri is missing in the request. " +
"Please ensure it is added to the request. If you have any questions, you may contact the administrator of the application.")
}
- if client.ApplicationType() == ApplicationTypeNative {
- return validateAuthReqRedirectURINative(client, uri)
- }
if strings.HasPrefix(uri, "https://") {
return checkURIAgainstRedirects(client, uri)
}
+ if client.ApplicationType() == ApplicationTypeNative {
+ return validateAuthReqRedirectURINative(client, uri)
+ }
if err := checkURIAgainstRedirects(client, uri); err != nil {
return err
}
@@ -351,15 +338,12 @@ func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.Res
// ValidateAuthReqRedirectURINative validates the passed redirect_uri and response_type to the registered uris and client type
func validateAuthReqRedirectURINative(client Client, uri string) error {
parsedURL, isLoopback := HTTPLoopbackOrLocalhost(uri)
- isCustomSchema := !(strings.HasPrefix(uri, "http://") || strings.HasPrefix(uri, "https://"))
+ isCustomSchema := !strings.HasPrefix(uri, "http://")
if err := checkURIAgainstRedirects(client, uri); err == nil {
if client.DevMode() {
return nil
}
- if !isLoopback && strings.HasPrefix(uri, "https://") {
- return nil
- }
- // The RedirectURIs are only valid for native clients when localhost or non-"http://" and "https://"
+ // The RedirectURIs are only valid for native clients when localhost or non-"http://"
if isLoopback || isCustomSchema {
return nil
}
@@ -389,11 +373,11 @@ func HTTPLoopbackOrLocalhost(rawURL string) (*url.URL, bool) {
if err != nil {
return nil, false
}
- if parsedURL.Scheme == "http" || parsedURL.Scheme == "https" {
- hostName := parsedURL.Hostname()
- return parsedURL, hostName == "localhost" || net.ParseIP(hostName).IsLoopback()
+ if parsedURL.Scheme != "http" {
+ return nil, false
}
- return nil, false
+ hostName := parsedURL.Hostname()
+ return parsedURL, hostName == "localhost" || net.ParseIP(hostName).IsLoopback()
}
// ValidateAuthReqResponseType validates the passed response_type to the registered response types
@@ -483,70 +467,41 @@ func AuthResponse(authReq AuthRequest, authorizer Authorizer, w http.ResponseWri
AuthResponseToken(w, r, authReq, authorizer, client)
}
-// AuthResponseCode handles the creation of a successful authentication response using an authorization code
+// AuthResponseCode creates the successful code authentication response
func AuthResponseCode(w http.ResponseWriter, r *http.Request, authReq AuthRequest, authorizer Authorizer) {
ctx, span := tracer.Start(r.Context(), "AuthResponseCode")
- defer span.End()
r = r.WithContext(ctx)
+ defer span.End()
- var err error
- if authReq.GetResponseMode() == oidc.ResponseModeFormPost {
- err = handleFormPostResponse(w, r, authReq, authorizer)
- } else {
- err = handleRedirectResponse(w, r, authReq, authorizer)
- }
-
+ code, err := CreateAuthRequestCode(r.Context(), authReq, authorizer.Storage(), authorizer.Crypto())
if err != nil {
AuthRequestError(w, r, authReq, err, authorizer)
+ return
+ }
+ codeResponse := struct {
+ Code string `schema:"code"`
+ State string `schema:"state,omitempty"`
+ }{
+ Code: code,
+ State: authReq.GetState(),
}
-}
-// handleFormPostResponse processes the authentication response using form post method
-func handleFormPostResponse(w http.ResponseWriter, r *http.Request, authReq AuthRequest, authorizer Authorizer) error {
- codeResponse, err := BuildAuthResponseCodeResponsePayload(r.Context(), authReq, authorizer)
+ if authReq.GetResponseMode() == oidc.ResponseModeFormPost {
+ err := AuthResponseFormPost(w, authReq.GetRedirectURI(), &codeResponse, authorizer.Encoder())
+ if err != nil {
+ AuthRequestError(w, r, authReq, err, authorizer)
+ return
+ }
+
+ return
+ }
+
+ callback, err := AuthResponseURL(authReq.GetRedirectURI(), authReq.GetResponseType(), authReq.GetResponseMode(), &codeResponse, authorizer.Encoder())
if err != nil {
- return err
+ AuthRequestError(w, r, authReq, err, authorizer)
+ return
}
- return AuthResponseFormPost(w, authReq.GetRedirectURI(), codeResponse, authorizer.Encoder())
-}
-
-// handleRedirectResponse processes the authentication response using the redirect method
-func handleRedirectResponse(w http.ResponseWriter, r *http.Request, authReq AuthRequest, authorizer Authorizer) error {
- callbackURL, err := BuildAuthResponseCallbackURL(r.Context(), authReq, authorizer)
- if err != nil {
- return err
- }
- http.Redirect(w, r, callbackURL, http.StatusFound)
- return nil
-}
-
-// BuildAuthResponseCodeResponsePayload generates the authorization code response payload for the authentication request
-func BuildAuthResponseCodeResponsePayload(ctx context.Context, authReq AuthRequest, authorizer Authorizer) (*CodeResponseType, error) {
- code, err := CreateAuthRequestCode(ctx, authReq, authorizer.Storage(), authorizer.Crypto())
- if err != nil {
- return nil, err
- }
-
- sessionState := ""
- if authRequestSessionState, ok := authReq.(AuthRequestSessionState); ok {
- sessionState = authRequestSessionState.GetSessionState()
- }
-
- return &CodeResponseType{
- Code: code,
- State: authReq.GetState(),
- SessionState: sessionState,
- }, nil
-}
-
-// BuildAuthResponseCallbackURL generates the callback URL for a successful authorization code response
-func BuildAuthResponseCallbackURL(ctx context.Context, authReq AuthRequest, authorizer Authorizer) (string, error) {
- codeResponse, err := BuildAuthResponseCodeResponsePayload(ctx, authReq, authorizer)
- if err != nil {
- return "", err
- }
-
- return AuthResponseURL(authReq.GetRedirectURI(), authReq.GetResponseType(), authReq.GetResponseMode(), codeResponse, authorizer.Encoder())
+ http.Redirect(w, r, callback, http.StatusFound)
}
// AuthResponseToken creates the successful token(s) authentication response
diff --git a/pkg/op/auth_request_test.go b/pkg/op/auth_request_test.go
index d1ea965..45627a5 100644
--- a/pkg/op/auth_request_test.go
+++ b/pkg/op/auth_request_test.go
@@ -11,15 +11,15 @@ import (
"reflect"
"testing"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/storage"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op/mock"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/zitadel/oidc/v3/example/server/storage"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/op/mock"
"github.com/zitadel/schema"
)
@@ -137,6 +137,11 @@ func TestValidateAuthRequest(t *testing.T) {
args{&oidc.AuthRequest{}, mock.NewMockStorageExpectValidClientID(t), nil},
oidc.ErrInvalidRequest(),
},
+ {
+ "scope openid missing fails",
+ args{&oidc.AuthRequest{Scopes: []string{"profile"}}, mock.NewMockStorageExpectValidClientID(t), nil},
+ oidc.ErrInvalidScope(),
+ },
{
"response_type missing fails",
args{&oidc.AuthRequest{Scopes: []string{"openid"}}, mock.NewMockStorageExpectValidClientID(t), nil},
@@ -282,6 +287,16 @@ func TestValidateAuthReqScopes(t *testing.T) {
err: true,
},
},
+ {
+ "scope openid missing fails",
+ args{
+ mock.NewClientExpectAny(t, op.ApplicationTypeWeb),
+ []string{"email"},
+ },
+ res{
+ err: true,
+ },
+ },
{
"scope ok",
args{
@@ -433,24 +448,6 @@ func TestValidateAuthReqRedirectURI(t *testing.T) {
},
false,
},
- {
- "code flow registered https loopback v4 native ok",
- args{
- "https://127.0.0.1:4200/callback",
- mock.NewClientWithConfig(t, []string{"https://127.0.0.1/callback"}, op.ApplicationTypeNative, nil, false),
- oidc.ResponseTypeCode,
- },
- false,
- },
- {
- "code flow registered https loopback v6 native ok",
- args{
- "https://[::1]:4200/callback",
- mock.NewClientWithConfig(t, []string{"https://[::1]/callback"}, op.ApplicationTypeNative, nil, false),
- oidc.ResponseTypeCode,
- },
- false,
- },
{
"code flow unregistered http native fails",
args{
@@ -1090,34 +1087,6 @@ func TestAuthResponseCode(t *testing.T) {
wantBody: "",
},
},
- {
- name: "success with state and session_state",
- args: args{
- authReq: &storage.AuthRequestWithSessionState{
- AuthRequest: &storage.AuthRequest{
- ID: "id1",
- TransferState: "state1",
- },
- SessionState: "session_state1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- authorizer.EXPECT().Encoder().Return(schema.NewEncoder())
- return authorizer
- },
- },
- res: res{
- wantCode: http.StatusFound,
- wantLocationHeader: "/auth/callback/?code=id1&session_state=session_state1&state=state1",
- wantBody: "",
- },
- },
{
name: "success without state", // reproduce issue #415
args: args{
@@ -1225,133 +1194,6 @@ func Test_parseAuthorizeCallbackRequest(t *testing.T) {
}
}
-func TestBuildAuthResponseCodeResponsePayload(t *testing.T) {
- type args struct {
- authReq op.AuthRequest
- authorizer func(*testing.T) op.Authorizer
- }
- type res struct {
- wantCode string
- wantState string
- wantSessionState string
- wantErr bool
- }
- tests := []struct {
- name string
- args args
- res res
- }{
- {
- name: "create code error",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{
- returnErr: io.ErrClosedPipe,
- })
- return authorizer
- },
- },
- res: res{
- wantErr: true,
- },
- },
- {
- name: "success with state",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- TransferState: "state1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- return authorizer
- },
- },
- res: res{
- wantCode: "id1",
- wantState: "state1",
- },
- },
- {
- name: "success without state",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- TransferState: "",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- return authorizer
- },
- },
- res: res{
- wantCode: "id1",
- wantState: "",
- },
- },
- {
- name: "success with session_state",
- args: args{
- authReq: &storage.AuthRequestWithSessionState{
- AuthRequest: &storage.AuthRequest{
- ID: "id1",
- TransferState: "state1",
- },
- SessionState: "session_state1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- return authorizer
- },
- },
- res: res{
- wantCode: "id1",
- wantState: "state1",
- wantSessionState: "session_state1",
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := op.BuildAuthResponseCodeResponsePayload(context.Background(), tt.args.authReq, tt.args.authorizer(t))
- if tt.res.wantErr {
- assert.Error(t, err)
- return
- }
- require.NoError(t, err)
- assert.Equal(t, tt.res.wantCode, got.Code)
- assert.Equal(t, tt.res.wantState, got.State)
- assert.Equal(t, tt.res.wantSessionState, got.SessionState)
- })
- }
-}
-
func TestValidateAuthReqIDTokenHint(t *testing.T) {
token, _ := tu.ValidIDToken()
tests := []struct {
@@ -1382,231 +1224,3 @@ func TestValidateAuthReqIDTokenHint(t *testing.T) {
})
}
}
-
-func TestBuildAuthResponseCallbackURL(t *testing.T) {
- type args struct {
- authReq op.AuthRequest
- authorizer func(*testing.T) op.Authorizer
- }
- type res struct {
- wantURL string
- wantErr bool
- }
- tests := []struct {
- name string
- args args
- res res
- }{
- {
- name: "error when generating code response",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{
- returnErr: io.ErrClosedPipe,
- })
- return authorizer
- },
- },
- res: res{
- wantErr: true,
- },
- },
- {
- name: "error when generating callback URL",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- CallbackURI: "://invalid-url",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- authorizer.EXPECT().Encoder().Return(schema.NewEncoder())
- return authorizer
- },
- },
- res: res{
- wantErr: true,
- },
- },
- {
- name: "success with state",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- CallbackURI: "https://example.com/callback",
- TransferState: "state1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- authorizer.EXPECT().Encoder().Return(schema.NewEncoder())
- return authorizer
- },
- },
- res: res{
- wantURL: "https://example.com/callback?code=id1&state=state1",
- wantErr: false,
- },
- },
- {
- name: "success without state",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- CallbackURI: "https://example.com/callback",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- authorizer.EXPECT().Encoder().Return(schema.NewEncoder())
- return authorizer
- },
- },
- res: res{
- wantURL: "https://example.com/callback?code=id1",
- wantErr: false,
- },
- },
- {
- name: "success with session_state",
- args: args{
- authReq: &storage.AuthRequestWithSessionState{
- AuthRequest: &storage.AuthRequest{
- ID: "id1",
- CallbackURI: "https://example.com/callback",
- TransferState: "state1",
- },
- SessionState: "session_state1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- authorizer.EXPECT().Encoder().Return(schema.NewEncoder())
- return authorizer
- },
- },
- res: res{
- wantURL: "https://example.com/callback?code=id1&session_state=session_state1&state=state1",
- wantErr: false,
- },
- },
- {
- name: "success with existing query parameters",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- CallbackURI: "https://example.com/callback?param=value",
- TransferState: "state1",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- authorizer.EXPECT().Encoder().Return(schema.NewEncoder())
- return authorizer
- },
- },
- res: res{
- wantURL: "https://example.com/callback?param=value&code=id1&state=state1",
- wantErr: false,
- },
- },
- {
- name: "success with fragment response mode",
- args: args{
- authReq: &storage.AuthRequest{
- ID: "id1",
- CallbackURI: "https://example.com/callback",
- TransferState: "state1",
- ResponseMode: "fragment",
- },
- authorizer: func(t *testing.T) op.Authorizer {
- ctrl := gomock.NewController(t)
- storage := mock.NewMockStorage(ctrl)
- storage.EXPECT().SaveAuthCode(gomock.Any(), "id1", "id1")
-
- authorizer := mock.NewMockAuthorizer(ctrl)
- authorizer.EXPECT().Storage().Return(storage)
- authorizer.EXPECT().Crypto().Return(&mockCrypto{})
- authorizer.EXPECT().Encoder().Return(schema.NewEncoder())
- return authorizer
- },
- },
- res: res{
- wantURL: "https://example.com/callback#code=id1&state=state1",
- wantErr: false,
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := op.BuildAuthResponseCallbackURL(context.Background(), tt.args.authReq, tt.args.authorizer(t))
- if tt.res.wantErr {
- assert.Error(t, err)
- return
- }
- require.NoError(t, err)
-
- if tt.res.wantURL != "" {
- // Parse the URLs to compare components instead of direct string comparison
- expectedURL, err := url.Parse(tt.res.wantURL)
- require.NoError(t, err)
- actualURL, err := url.Parse(got)
- require.NoError(t, err)
-
- // Compare the base parts (scheme, host, path)
- assert.Equal(t, expectedURL.Scheme, actualURL.Scheme)
- assert.Equal(t, expectedURL.Host, actualURL.Host)
- assert.Equal(t, expectedURL.Path, actualURL.Path)
-
- // Compare the fragment if any
- assert.Equal(t, expectedURL.Fragment, actualURL.Fragment)
-
- // For query parameters, compare them independently of order
- expectedQuery := expectedURL.Query()
- actualQuery := actualURL.Query()
-
- assert.Equal(t, len(expectedQuery), len(actualQuery), "Query parameter count does not match")
-
- for key, expectedValues := range expectedQuery {
- actualValues, exists := actualQuery[key]
- assert.True(t, exists, "Expected query parameter %s not found", key)
- assert.ElementsMatch(t, expectedValues, actualValues, "Values for parameter %s don't match", key)
- }
- }
- })
- }
-}
diff --git a/pkg/op/client.go b/pkg/op/client.go
index a4f44d3..913944c 100644
--- a/pkg/op/client.go
+++ b/pkg/op/client.go
@@ -7,8 +7,8 @@ import (
"net/url"
"time"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
//go:generate go get github.com/dmarkham/enumer
diff --git a/pkg/op/client_test.go b/pkg/op/client_test.go
index b416630..b772ba5 100644
--- a/pkg/op/client_test.go
+++ b/pkg/op/client_test.go
@@ -10,13 +10,13 @@ import (
"strings"
"testing"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op/mock"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/op/mock"
"github.com/zitadel/schema"
)
diff --git a/pkg/op/config.go b/pkg/op/config.go
index b271765..9fec7cc 100644
--- a/pkg/op/config.go
+++ b/pkg/op/config.go
@@ -30,7 +30,6 @@ type Configuration interface {
EndSessionEndpoint() *Endpoint
KeysEndpoint() *Endpoint
DeviceAuthorizationEndpoint() *Endpoint
- CheckSessionIframe() *Endpoint
AuthMethodPostSupported() bool
CodeMethodS256Supported() bool
@@ -50,9 +49,6 @@ type Configuration interface {
SupportedUILocales() []language.Tag
DeviceAuthorization() DeviceAuthorizationConfig
-
- BackChannelLogoutSupported() bool
- BackChannelLogoutSessionSupported() bool
}
type IssuerFromRequest func(r *http.Request) string
diff --git a/pkg/op/crypto.go b/pkg/op/crypto.go
index 01aaad3..6ab1e0a 100644
--- a/pkg/op/crypto.go
+++ b/pkg/op/crypto.go
@@ -1,7 +1,7 @@
package op
import (
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/crypto"
+ "github.com/zitadel/oidc/v3/pkg/crypto"
)
type Crypto interface {
diff --git a/pkg/op/device.go b/pkg/op/device.go
index 866cbc4..11638b0 100644
--- a/pkg/op/device.go
+++ b/pkg/op/device.go
@@ -9,12 +9,12 @@ import (
"math/big"
"net/http"
"net/url"
- "slices"
"strings"
"time"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ strs "github.com/zitadel/oidc/v3/pkg/strings"
)
type DeviceAuthorizationConfig struct {
@@ -91,7 +91,10 @@ func createDeviceAuthorization(ctx context.Context, req *oidc.DeviceAuthorizatio
}
config := o.DeviceAuthorization()
- deviceCode, _ := NewDeviceCode(RecommendedDeviceCodeBytes)
+ deviceCode, err := NewDeviceCode(RecommendedDeviceCodeBytes)
+ if err != nil {
+ return nil, NewStatusError(err, http.StatusInternalServerError)
+ }
userCode, err := NewUserCode([]rune(config.UserCode.CharSet), config.UserCode.CharAmount, config.UserCode.DashInterval)
if err != nil {
return nil, NewStatusError(err, http.StatusInternalServerError)
@@ -160,14 +163,11 @@ func ParseDeviceCodeRequest(r *http.Request, o OpenIDProvider) (*oidc.DeviceAuth
// results in a 22 character base64 encoded string.
const RecommendedDeviceCodeBytes = 16
-// NewDeviceCode generates a new cryptographically secure device code as a base64 encoded string.
-// The length of the string is nBytes * 4 / 3.
-// An error is never returned.
-//
-// TODO(v4): change return type to string alone.
func NewDeviceCode(nBytes int) (string, error) {
bytes := make([]byte, nBytes)
- rand.Read(bytes)
+ if _, err := rand.Read(bytes); err != nil {
+ return "", fmt.Errorf("%w getting entropy for device code", err)
+ }
return base64.RawURLEncoding.EncodeToString(bytes), nil
}
@@ -276,7 +276,7 @@ func (r *DeviceAuthorizationState) GetAMR() []string {
}
func (r *DeviceAuthorizationState) GetAudience() []string {
- if !slices.Contains(r.Audience, r.ClientID) {
+ if !strs.Contains(r.Audience, r.ClientID) {
r.Audience = append(r.Audience, r.ClientID)
}
return r.Audience
@@ -344,11 +344,10 @@ func CreateDeviceTokenResponse(ctx context.Context, tokenRequest TokenRequest, c
RefreshToken: refreshToken,
TokenType: oidc.BearerToken,
ExpiresIn: uint64(validity.Seconds()),
- Scope: tokenRequest.GetScopes(),
}
// TODO(v4): remove type assertion
- if idTokenRequest, ok := tokenRequest.(IDTokenRequest); ok && slices.Contains(tokenRequest.GetScopes(), oidc.ScopeOpenID) {
+ if idTokenRequest, ok := tokenRequest.(IDTokenRequest); ok && strs.Contains(tokenRequest.GetScopes(), oidc.ScopeOpenID) {
response.IDToken, err = CreateIDToken(ctx, IssuerFromContext(ctx), idTokenRequest, client.IDTokenLifetime(), accessToken, "", creator.Storage(), client)
if err != nil {
return nil, err
diff --git a/pkg/op/device_test.go b/pkg/op/device_test.go
index a7b5c4e..570b943 100644
--- a/pkg/op/device_test.go
+++ b/pkg/op/device_test.go
@@ -13,12 +13,12 @@ import (
"testing"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/storage"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/zitadel/oidc/v3/example/server/storage"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
func Test_deviceAuthorizationHandler(t *testing.T) {
@@ -145,11 +145,21 @@ func runWithRandReader(r io.Reader, f func()) {
}
func TestNewDeviceCode(t *testing.T) {
- for i := 1; i <= 32; i++ {
- got, err := op.NewDeviceCode(i)
- require.NoError(t, err)
- assert.Len(t, got, base64.RawURLEncoding.EncodedLen(i))
- }
+ t.Run("reader error", func(t *testing.T) {
+ runWithRandReader(errReader{}, func() {
+ _, err := op.NewDeviceCode(16)
+ require.Error(t, err)
+ })
+ })
+
+ t.Run("different lengths, rand reader", func(t *testing.T) {
+ for i := 1; i <= 32; i++ {
+ got, err := op.NewDeviceCode(i)
+ require.NoError(t, err)
+ assert.Len(t, got, base64.RawURLEncoding.EncodedLen(i))
+ }
+ })
+
}
func TestNewUserCode(t *testing.T) {
diff --git a/pkg/op/discovery.go b/pkg/op/discovery.go
index 9b3ddb6..cd08580 100644
--- a/pkg/op/discovery.go
+++ b/pkg/op/discovery.go
@@ -6,8 +6,8 @@ import (
jose "github.com/go-jose/go-jose/v4"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type DiscoverStorage interface {
@@ -45,7 +45,6 @@ func CreateDiscoveryConfig(ctx context.Context, config Configuration, storage Di
EndSessionEndpoint: config.EndSessionEndpoint().Absolute(issuer),
JwksURI: config.KeysEndpoint().Absolute(issuer),
DeviceAuthorizationEndpoint: config.DeviceAuthorizationEndpoint().Absolute(issuer),
- CheckSessionIframe: config.CheckSessionIframe().Absolute(issuer),
ScopesSupported: Scopes(config),
ResponseTypesSupported: ResponseTypes(config),
GrantTypesSupported: GrantTypes(config),
@@ -62,8 +61,6 @@ func CreateDiscoveryConfig(ctx context.Context, config Configuration, storage Di
CodeChallengeMethodsSupported: CodeChallengeMethods(config),
UILocalesSupported: config.SupportedUILocales(),
RequestParameterSupported: config.RequestObjectSupported(),
- BackChannelLogoutSupported: config.BackChannelLogoutSupported(),
- BackChannelLogoutSessionSupported: config.BackChannelLogoutSessionSupported(),
}
}
@@ -95,17 +92,11 @@ func createDiscoveryConfigV2(ctx context.Context, config Configuration, storage
CodeChallengeMethodsSupported: CodeChallengeMethods(config),
UILocalesSupported: config.SupportedUILocales(),
RequestParameterSupported: config.RequestObjectSupported(),
- BackChannelLogoutSupported: config.BackChannelLogoutSupported(),
- BackChannelLogoutSessionSupported: config.BackChannelLogoutSessionSupported(),
}
}
func Scopes(c Configuration) []string {
- provider, ok := c.(*Provider)
- if ok && provider.config.SupportedScopes != nil {
- return provider.config.SupportedScopes
- }
- return DefaultSupportedScopes
+ return DefaultSupportedScopes // TODO: config
}
func ResponseTypes(c Configuration) []string {
@@ -140,7 +131,7 @@ func GrantTypes(c Configuration) []oidc.GrantType {
}
func SubjectTypes(c Configuration) []string {
- return []string{"public"} // TODO: config
+ return []string{"public"} //TODO: config
}
func SigAlgorithms(ctx context.Context, storage DiscoverStorage) []string {
diff --git a/pkg/op/discovery_test.go b/pkg/op/discovery_test.go
index 63f1b98..cb4cfba 100644
--- a/pkg/op/discovery_test.go
+++ b/pkg/op/discovery_test.go
@@ -11,9 +11,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op/mock"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/op/mock"
)
func TestDiscover(t *testing.T) {
@@ -81,11 +81,6 @@ func Test_scopes(t *testing.T) {
args{},
op.DefaultSupportedScopes,
},
- {
- "custom scopes",
- args{newTestProvider(&op.Config{SupportedScopes: []string{"test1", "test2"}})},
- []string{"test1", "test2"},
- },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/op/endpoint_test.go b/pkg/op/endpoint_test.go
index 5b98c6e..bf112ef 100644
--- a/pkg/op/endpoint_test.go
+++ b/pkg/op/endpoint_test.go
@@ -3,8 +3,8 @@ package op_test
import (
"testing"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
"github.com/stretchr/testify/require"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
func TestEndpoint_Path(t *testing.T) {
diff --git a/pkg/op/error.go b/pkg/op/error.go
index 272f85e..44b1798 100644
--- a/pkg/op/error.go
+++ b/pkg/op/error.go
@@ -7,8 +7,8 @@ import (
"log/slog"
"net/http"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type ErrAuthRequest interface {
@@ -46,12 +46,6 @@ func AuthRequestError(w http.ResponseWriter, r *http.Request, authReq ErrAuthReq
return
}
e.State = authReq.GetState()
- var sessionState string
- authRequestSessionState, ok := authReq.(AuthRequestSessionState)
- if ok {
- sessionState = authRequestSessionState.GetSessionState()
- }
- e.SessionState = sessionState
var responseMode oidc.ResponseMode
if rm, ok := authReq.(interface{ GetResponseMode() oidc.ResponseMode }); ok {
responseMode = rm.GetResponseMode()
@@ -98,12 +92,6 @@ func TryErrorRedirect(ctx context.Context, authReq ErrAuthRequest, parent error,
}
e.State = authReq.GetState()
- var sessionState string
- authRequestSessionState, ok := authReq.(AuthRequestSessionState)
- if ok {
- sessionState = authRequestSessionState.GetSessionState()
- }
- e.SessionState = sessionState
var responseMode oidc.ResponseMode
if rm, ok := authReq.(interface{ GetResponseMode() oidc.ResponseMode }); ok {
responseMode = rm.GetResponseMode()
diff --git a/pkg/op/error_test.go b/pkg/op/error_test.go
index 9271cf1..170039c 100644
--- a/pkg/op/error_test.go
+++ b/pkg/op/error_test.go
@@ -11,9 +11,9 @@ import (
"strings"
"testing"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/schema"
)
@@ -428,8 +428,7 @@ func TestTryErrorRedirect(t *testing.T) {
parent: oidc.ErrInteractionRequired().WithDescription("sign in"),
},
want: &Redirect{
- Header: make(http.Header),
- URL: "http://example.com/callback?error=interaction_required&error_description=sign+in&state=state1",
+ URL: "http://example.com/callback?error=interaction_required&error_description=sign+in&state=state1",
},
wantLog: `{
"level":"WARN",
diff --git a/pkg/op/keys.go b/pkg/op/keys.go
index 97e400b..c96c456 100644
--- a/pkg/op/keys.go
+++ b/pkg/op/keys.go
@@ -6,7 +6,7 @@ import (
jose "github.com/go-jose/go-jose/v4"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
)
type KeyProvider interface {
diff --git a/pkg/op/keys_test.go b/pkg/op/keys_test.go
index 9c80878..3662739 100644
--- a/pkg/op/keys_test.go
+++ b/pkg/op/keys_test.go
@@ -11,9 +11,9 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op/mock"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/op/mock"
)
func TestKeys(t *testing.T) {
diff --git a/pkg/op/mock/authorizer.mock.go b/pkg/op/mock/authorizer.mock.go
index 56b28e0..c7703f1 100644
--- a/pkg/op/mock/authorizer.mock.go
+++ b/pkg/op/mock/authorizer.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: Authorizer)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: Authorizer)
// Package mock is a generated GoMock package.
package mock
@@ -9,9 +9,9 @@ import (
slog "log/slog"
reflect "reflect"
- http "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- op "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
gomock "github.com/golang/mock/gomock"
+ http "github.com/zitadel/oidc/v3/pkg/http"
+ op "github.com/zitadel/oidc/v3/pkg/op"
)
// MockAuthorizer is a mock of Authorizer interface.
diff --git a/pkg/op/mock/authorizer.mock.impl.go b/pkg/op/mock/authorizer.mock.impl.go
index 73c4154..59e8fa3 100644
--- a/pkg/op/mock/authorizer.mock.impl.go
+++ b/pkg/op/mock/authorizer.mock.impl.go
@@ -8,8 +8,8 @@ import (
"github.com/golang/mock/gomock"
"github.com/zitadel/schema"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
func NewAuthorizer(t *testing.T) op.Authorizer {
diff --git a/pkg/op/mock/client.go b/pkg/op/mock/client.go
index e2a5e85..f01e3ec 100644
--- a/pkg/op/mock/client.go
+++ b/pkg/op/mock/client.go
@@ -5,8 +5,8 @@ import (
"github.com/golang/mock/gomock"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
func NewClient(t *testing.T) op.Client {
diff --git a/pkg/op/mock/client.mock.go b/pkg/op/mock/client.mock.go
index 93eca67..9be0807 100644
--- a/pkg/op/mock/client.mock.go
+++ b/pkg/op/mock/client.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: Client)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: Client)
// Package mock is a generated GoMock package.
package mock
@@ -8,9 +8,9 @@ import (
reflect "reflect"
time "time"
- oidc "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- op "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
gomock "github.com/golang/mock/gomock"
+ oidc "github.com/zitadel/oidc/v3/pkg/oidc"
+ op "github.com/zitadel/oidc/v3/pkg/op"
)
// MockClient is a mock of Client interface.
diff --git a/pkg/op/mock/configuration.mock.go b/pkg/op/mock/configuration.mock.go
index bf51035..f392a45 100644
--- a/pkg/op/mock/configuration.mock.go
+++ b/pkg/op/mock/configuration.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: Configuration)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: Configuration)
// Package mock is a generated GoMock package.
package mock
@@ -8,8 +8,8 @@ import (
http "net/http"
reflect "reflect"
- op "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
gomock "github.com/golang/mock/gomock"
+ op "github.com/zitadel/oidc/v3/pkg/op"
language "golang.org/x/text/language"
)
@@ -78,48 +78,6 @@ func (mr *MockConfigurationMockRecorder) AuthorizationEndpoint() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthorizationEndpoint", reflect.TypeOf((*MockConfiguration)(nil).AuthorizationEndpoint))
}
-// BackChannelLogoutSessionSupported mocks base method.
-func (m *MockConfiguration) BackChannelLogoutSessionSupported() bool {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "BackChannelLogoutSessionSupported")
- ret0, _ := ret[0].(bool)
- return ret0
-}
-
-// BackChannelLogoutSessionSupported indicates an expected call of BackChannelLogoutSessionSupported.
-func (mr *MockConfigurationMockRecorder) BackChannelLogoutSessionSupported() *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BackChannelLogoutSessionSupported", reflect.TypeOf((*MockConfiguration)(nil).BackChannelLogoutSessionSupported))
-}
-
-// BackChannelLogoutSupported mocks base method.
-func (m *MockConfiguration) BackChannelLogoutSupported() bool {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "BackChannelLogoutSupported")
- ret0, _ := ret[0].(bool)
- return ret0
-}
-
-// BackChannelLogoutSupported indicates an expected call of BackChannelLogoutSupported.
-func (mr *MockConfigurationMockRecorder) BackChannelLogoutSupported() *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BackChannelLogoutSupported", reflect.TypeOf((*MockConfiguration)(nil).BackChannelLogoutSupported))
-}
-
-// CheckSessionIframe mocks base method.
-func (m *MockConfiguration) CheckSessionIframe() *op.Endpoint {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "CheckSessionIframe")
- ret0, _ := ret[0].(*op.Endpoint)
- return ret0
-}
-
-// CheckSessionIframe indicates an expected call of CheckSessionIframe.
-func (mr *MockConfigurationMockRecorder) CheckSessionIframe() *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckSessionIframe", reflect.TypeOf((*MockConfiguration)(nil).CheckSessionIframe))
-}
-
// CodeMethodS256Supported mocks base method.
func (m *MockConfiguration) CodeMethodS256Supported() bool {
m.ctrl.T.Helper()
diff --git a/pkg/op/mock/discovery.mock.go b/pkg/op/mock/discovery.mock.go
index c85f91b..a27f8ef 100644
--- a/pkg/op/mock/discovery.mock.go
+++ b/pkg/op/mock/discovery.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: DiscoverStorage)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: DiscoverStorage)
// Package mock is a generated GoMock package.
package mock
diff --git a/pkg/op/mock/generate.go b/pkg/op/mock/generate.go
index 3d58ab7..e5cab3e 100644
--- a/pkg/op/mock/generate.go
+++ b/pkg/op/mock/generate.go
@@ -1,11 +1,11 @@
package mock
//go:generate go install github.com/golang/mock/mockgen@v1.6.0
-//go:generate mockgen -package mock -destination ./storage.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op Storage
-//go:generate mockgen -package mock -destination ./authorizer.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op Authorizer
-//go:generate mockgen -package mock -destination ./client.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op Client
-//go:generate mockgen -package mock -destination ./glob.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op HasRedirectGlobs
-//go:generate mockgen -package mock -destination ./configuration.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op Configuration
-//go:generate mockgen -package mock -destination ./discovery.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op DiscoverStorage
-//go:generate mockgen -package mock -destination ./signer.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op SigningKey,Key
-//go:generate mockgen -package mock -destination ./key.mock.go git.christmann.info/LARA/zitadel-oidc/v3/pkg/op KeyProvider
+//go:generate mockgen -package mock -destination ./storage.mock.go github.com/zitadel/oidc/v3/pkg/op Storage
+//go:generate mockgen -package mock -destination ./authorizer.mock.go github.com/zitadel/oidc/v3/pkg/op Authorizer
+//go:generate mockgen -package mock -destination ./client.mock.go github.com/zitadel/oidc/v3/pkg/op Client
+//go:generate mockgen -package mock -destination ./glob.mock.go github.com/zitadel/oidc/v3/pkg/op HasRedirectGlobs
+//go:generate mockgen -package mock -destination ./configuration.mock.go github.com/zitadel/oidc/v3/pkg/op Configuration
+//go:generate mockgen -package mock -destination ./discovery.mock.go github.com/zitadel/oidc/v3/pkg/op DiscoverStorage
+//go:generate mockgen -package mock -destination ./signer.mock.go github.com/zitadel/oidc/v3/pkg/op SigningKey,Key
+//go:generate mockgen -package mock -destination ./key.mock.go github.com/zitadel/oidc/v3/pkg/op KeyProvider
diff --git a/pkg/op/mock/glob.go b/pkg/op/mock/glob.go
index 8149c8f..cade476 100644
--- a/pkg/op/mock/glob.go
+++ b/pkg/op/mock/glob.go
@@ -3,9 +3,9 @@ package mock
import (
"testing"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- op "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
gomock "github.com/golang/mock/gomock"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ op "github.com/zitadel/oidc/v3/pkg/op"
)
func NewHasRedirectGlobs(t *testing.T) op.HasRedirectGlobs {
diff --git a/pkg/op/mock/glob.mock.go b/pkg/op/mock/glob.mock.go
index ebdc333..cf9996e 100644
--- a/pkg/op/mock/glob.mock.go
+++ b/pkg/op/mock/glob.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: HasRedirectGlobs)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: HasRedirectGlobs)
// Package mock is a generated GoMock package.
package mock
@@ -8,9 +8,9 @@ import (
reflect "reflect"
time "time"
- oidc "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- op "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
gomock "github.com/golang/mock/gomock"
+ oidc "github.com/zitadel/oidc/v3/pkg/oidc"
+ op "github.com/zitadel/oidc/v3/pkg/op"
)
// MockHasRedirectGlobs is a mock of HasRedirectGlobs interface.
diff --git a/pkg/op/mock/key.mock.go b/pkg/op/mock/key.mock.go
index d9ee857..122e852 100644
--- a/pkg/op/mock/key.mock.go
+++ b/pkg/op/mock/key.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: KeyProvider)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: KeyProvider)
// Package mock is a generated GoMock package.
package mock
@@ -8,8 +8,8 @@ import (
context "context"
reflect "reflect"
- op "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
gomock "github.com/golang/mock/gomock"
+ op "github.com/zitadel/oidc/v3/pkg/op"
)
// MockKeyProvider is a mock of KeyProvider interface.
diff --git a/pkg/op/mock/signer.mock.go b/pkg/op/mock/signer.mock.go
index 751ce60..e1bab91 100644
--- a/pkg/op/mock/signer.mock.go
+++ b/pkg/op/mock/signer.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: SigningKey,Key)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: SigningKey,Key)
// Package mock is a generated GoMock package.
package mock
diff --git a/pkg/op/mock/storage.mock.go b/pkg/op/mock/storage.mock.go
index 0df9830..02a7c5c 100644
--- a/pkg/op/mock/storage.mock.go
+++ b/pkg/op/mock/storage.mock.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.christmann.info/LARA/zitadel-oidc/v3/pkg/op (interfaces: Storage)
+// Source: github.com/zitadel/oidc/v3/pkg/op (interfaces: Storage)
// Package mock is a generated GoMock package.
package mock
@@ -9,10 +9,10 @@ import (
reflect "reflect"
time "time"
- oidc "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- op "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
jose "github.com/go-jose/go-jose/v4"
gomock "github.com/golang/mock/gomock"
+ oidc "github.com/zitadel/oidc/v3/pkg/oidc"
+ op "github.com/zitadel/oidc/v3/pkg/op"
)
// MockStorage is a mock of Storage interface.
diff --git a/pkg/op/mock/storage.mock.impl.go b/pkg/op/mock/storage.mock.impl.go
index 96e08a9..002da7e 100644
--- a/pkg/op/mock/storage.mock.impl.go
+++ b/pkg/op/mock/storage.mock.impl.go
@@ -8,8 +8,8 @@ import (
"github.com/golang/mock/gomock"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
func NewStorage(t *testing.T) op.Storage {
diff --git a/pkg/op/op.go b/pkg/op/op.go
index 76c2c89..61c2449 100644
--- a/pkg/op/op.go
+++ b/pkg/op/op.go
@@ -14,8 +14,8 @@ import (
"go.opentelemetry.io/otel"
"golang.org/x/text/language"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
const (
@@ -158,19 +158,16 @@ func authCallbackPath(o OpenIDProvider) string {
}
type Config struct {
- CryptoKey [32]byte
- DefaultLogoutRedirectURI string
- CodeMethodS256 bool
- AuthMethodPost bool
- AuthMethodPrivateKeyJWT bool
- GrantTypeRefreshToken bool
- RequestObjectSupported bool
- SupportedUILocales []language.Tag
- SupportedClaims []string
- SupportedScopes []string
- DeviceAuthorization DeviceAuthorizationConfig
- BackChannelLogoutSupported bool
- BackChannelLogoutSessionSupported bool
+ CryptoKey [32]byte
+ DefaultLogoutRedirectURI string
+ CodeMethodS256 bool
+ AuthMethodPost bool
+ AuthMethodPrivateKeyJWT bool
+ GrantTypeRefreshToken bool
+ RequestObjectSupported bool
+ SupportedUILocales []language.Tag
+ SupportedClaims []string
+ DeviceAuthorization DeviceAuthorizationConfig
}
// Endpoints defines endpoint routes.
@@ -339,10 +336,6 @@ func (o *Provider) DeviceAuthorizationEndpoint() *Endpoint {
return o.endpoints.DeviceAuthorization
}
-func (o *Provider) CheckSessionIframe() *Endpoint {
- return o.endpoints.CheckSessionIframe
-}
-
func (o *Provider) KeysEndpoint() *Endpoint {
return o.endpoints.JwksURI
}
@@ -418,14 +411,6 @@ func (o *Provider) DeviceAuthorization() DeviceAuthorizationConfig {
return o.config.DeviceAuthorization
}
-func (o *Provider) BackChannelLogoutSupported() bool {
- return o.config.BackChannelLogoutSupported
-}
-
-func (o *Provider) BackChannelLogoutSessionSupported() bool {
- return o.config.BackChannelLogoutSessionSupported
-}
-
func (o *Provider) Storage() Storage {
return o.storage
}
diff --git a/pkg/op/op_test.go b/pkg/op/op_test.go
index e1ac0bd..83032d4 100644
--- a/pkg/op/op_test.go
+++ b/pkg/op/op_test.go
@@ -11,12 +11,12 @@ import (
"testing"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/example/server/storage"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/zitadel/oidc/v3/example/server/storage"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
"golang.org/x/text/language"
)
@@ -232,7 +232,7 @@ func TestRoutes(t *testing.T) {
"scope": oidc.SpaceDelimitedArray{oidc.ScopeOpenID, oidc.ScopeOfflineAccess}.String(),
},
wantCode: http.StatusOK,
- contains: []string{`{"access_token":"`, `","token_type":"Bearer","expires_in":299,"scope":"openid offline_access"}`},
+ contains: []string{`{"access_token":"`, `","token_type":"Bearer","expires_in":299}`},
},
{
// This call will fail. A successful test is already
diff --git a/pkg/op/probes.go b/pkg/op/probes.go
index fa713da..cb3853d 100644
--- a/pkg/op/probes.go
+++ b/pkg/op/probes.go
@@ -5,7 +5,7 @@ import (
"errors"
"net/http"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
)
type ProbesFn func(context.Context) error
diff --git a/pkg/op/server.go b/pkg/op/server.go
index d45b734..829618c 100644
--- a/pkg/op/server.go
+++ b/pkg/op/server.go
@@ -5,9 +5,9 @@ import (
"net/http"
"net/url"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/muhlemmer/gu"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// Server describes the interface that needs to be implemented to serve
@@ -218,8 +218,7 @@ type Response struct {
// without custom headers.
func NewResponse(data any) *Response {
return &Response{
- Header: make(http.Header),
- Data: data,
+ Data: data,
}
}
@@ -243,14 +242,11 @@ type Redirect struct {
}
func NewRedirect(url string) *Redirect {
- return &Redirect{
- Header: make(http.Header),
- URL: url,
- }
+ return &Redirect{URL: url}
}
func (red *Redirect) writeOut(w http.ResponseWriter, r *http.Request) {
- gu.MapMerge(red.Header, w.Header())
+ gu.MapMerge(r.Header, w.Header())
http.Redirect(w, r, red.URL, http.StatusFound)
}
diff --git a/pkg/op/server_http.go b/pkg/op/server_http.go
index d71a354..725dd64 100644
--- a/pkg/op/server_http.go
+++ b/pkg/op/server_http.go
@@ -6,11 +6,11 @@ import (
"net/http"
"net/url"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/go-chi/chi/v5"
"github.com/rs/cors"
"github.com/zitadel/logging"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/schema"
)
diff --git a/pkg/op/server_http_routes_test.go b/pkg/op/server_http_routes_test.go
index 02200ee..2c83ad3 100644
--- a/pkg/op/server_http_routes_test.go
+++ b/pkg/op/server_http_routes_test.go
@@ -14,9 +14,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/client"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ "github.com/zitadel/oidc/v3/pkg/client"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
func jwtProfile() (string, error) {
@@ -145,7 +145,7 @@ func TestServerRoutes(t *testing.T) {
"assertion": jwtProfileToken,
},
wantCode: http.StatusOK,
- contains: []string{`{"access_token":`, `"token_type":"Bearer","expires_in":299,"scope":"openid"}`},
+ contains: []string{`{"access_token":`, `"token_type":"Bearer","expires_in":299}`},
},
{
name: "Token exchange",
@@ -174,7 +174,7 @@ func TestServerRoutes(t *testing.T) {
"scope": oidc.SpaceDelimitedArray{oidc.ScopeOpenID, oidc.ScopeOfflineAccess}.String(),
},
wantCode: http.StatusOK,
- contains: []string{`{"access_token":"`, `","token_type":"Bearer","expires_in":299,"scope":"openid offline_access"}`},
+ contains: []string{`{"access_token":"`, `","token_type":"Bearer","expires_in":299}`},
},
{
// This call will fail. A successful test is already
diff --git a/pkg/op/server_http_test.go b/pkg/op/server_http_test.go
index 75d02ca..9ff07bc 100644
--- a/pkg/op/server_http_test.go
+++ b/pkg/op/server_http_test.go
@@ -14,11 +14,11 @@ import (
"testing"
"time"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/schema"
)
diff --git a/pkg/op/server_legacy.go b/pkg/op/server_legacy.go
index 06e4e93..126fde1 100644
--- a/pkg/op/server_legacy.go
+++ b/pkg/op/server_legacy.go
@@ -6,8 +6,8 @@ import (
"net/http"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/go-chi/chi/v5"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// ExtendedLegacyServer allows embedding [LegacyServer] in a struct,
diff --git a/pkg/op/session.go b/pkg/op/session.go
index ac663c9..8ac530d 100644
--- a/pkg/op/session.go
+++ b/pkg/op/session.go
@@ -8,8 +8,8 @@ import (
"net/url"
"path"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type SessionEnder interface {
@@ -73,8 +73,6 @@ func ValidateEndSessionRequest(ctx context.Context, req *oidc.EndSessionRequest,
session := &EndSessionRequest{
RedirectURI: ender.DefaultLogoutRedirectURI(),
- LogoutHint: req.LogoutHint,
- UILocales: req.UILocales,
}
if req.IdTokenHint != "" {
claims, err := VerifyIDTokenHint[*oidc.IDTokenClaims](ctx, req.IdTokenHint, ender.IDTokenHintVerifier(ctx))
diff --git a/pkg/op/storage.go b/pkg/op/storage.go
index 2dbd124..8488b28 100644
--- a/pkg/op/storage.go
+++ b/pkg/op/storage.go
@@ -6,9 +6,8 @@ import (
"time"
jose "github.com/go-jose/go-jose/v4"
- "golang.org/x/text/language"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type AuthStorage interface {
@@ -145,12 +144,6 @@ type CanSetUserinfoFromRequest interface {
SetUserinfoFromRequest(ctx context.Context, userinfo *oidc.UserInfo, request IDTokenRequest, scopes []string) error
}
-// CanGetPrivateClaimsFromRequest is an optional additional interface that may be implemented by
-// implementors of Storage. It allows setting the jwt token claims based on the request.
-type CanGetPrivateClaimsFromRequest interface {
- GetPrivateClaimsFromRequest(ctx context.Context, request TokenRequest, restrictedScopes []string) (map[string]any, error)
-}
-
// Storage is a required parameter for NewOpenIDProvider(). In addition to the
// embedded interfaces below, if the passed Storage implements ClientCredentialsStorage
// then the grant type "client_credentials" will be supported. In that case, the access
@@ -171,8 +164,6 @@ type EndSessionRequest struct {
ClientID string
IDTokenHintClaims *oidc.IDTokenClaims
RedirectURI string
- LogoutHint string
- UILocales []language.Tag
}
var ErrDuplicateUserCode = errors.New("user code already exists")
diff --git a/pkg/op/token.go b/pkg/op/token.go
index 2e25d05..b45789b 100644
--- a/pkg/op/token.go
+++ b/pkg/op/token.go
@@ -2,11 +2,11 @@ package op
import (
"context"
- "slices"
"time"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/crypto"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/crypto"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/strings"
)
type TokenCreator interface {
@@ -65,7 +65,6 @@ func CreateTokenResponse(ctx context.Context, request IDTokenRequest, client Cli
TokenType: oidc.BearerToken,
ExpiresIn: exp,
State: state,
- Scope: request.GetScopes(),
}, nil
}
@@ -83,13 +82,13 @@ func createTokens(ctx context.Context, tokenRequest TokenRequest, storage Storag
func needsRefreshToken(tokenRequest TokenRequest, client AccessTokenClient) bool {
switch req := tokenRequest.(type) {
case AuthRequest:
- return slices.Contains(req.GetScopes(), oidc.ScopeOfflineAccess) && req.GetResponseType() == oidc.ResponseTypeCode && ValidateGrantType(client, oidc.GrantTypeRefreshToken)
+ return strings.Contains(req.GetScopes(), oidc.ScopeOfflineAccess) && req.GetResponseType() == oidc.ResponseTypeCode && ValidateGrantType(client, oidc.GrantTypeRefreshToken)
case TokenExchangeRequest:
return req.GetRequestedTokenType() == oidc.RefreshTokenType
case RefreshTokenRequest:
return true
case *DeviceAuthorizationState:
- return slices.Contains(req.GetScopes(), oidc.ScopeOfflineAccess) && ValidateGrantType(client, oidc.GrantTypeRefreshToken)
+ return strings.Contains(req.GetScopes(), oidc.ScopeOfflineAccess) && ValidateGrantType(client, oidc.GrantTypeRefreshToken)
default:
return false
}
@@ -147,11 +146,7 @@ func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, ex
tokenExchangeRequest,
)
} else {
- if fromRequest, ok := storage.(CanGetPrivateClaimsFromRequest); ok {
- privateClaims, err = fromRequest.GetPrivateClaimsFromRequest(ctx, tokenRequest, removeUserinfoScopes(restrictedScopes))
- } else {
- privateClaims, err = storage.GetPrivateClaimsFromScopes(ctx, tokenRequest.GetSubject(), client.GetID(), removeUserinfoScopes(restrictedScopes))
- }
+ privateClaims, err = storage.GetPrivateClaimsFromScopes(ctx, tokenRequest.GetSubject(), client.GetID(), removeUserinfoScopes(restrictedScopes))
}
if err != nil {
diff --git a/pkg/op/token_client_credentials.go b/pkg/op/token_client_credentials.go
index ddb2fbf..7f1debe 100644
--- a/pkg/op/token_client_credentials.go
+++ b/pkg/op/token_client_credentials.go
@@ -5,8 +5,8 @@ import (
"net/http"
"net/url"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// ClientCredentialsExchange handles the OAuth 2.0 client_credentials grant, including
@@ -120,6 +120,5 @@ func CreateClientCredentialsTokenResponse(ctx context.Context, tokenRequest Toke
AccessToken: accessToken,
TokenType: oidc.BearerToken,
ExpiresIn: uint64(validity.Seconds()),
- Scope: tokenRequest.GetScopes(),
}, nil
}
diff --git a/pkg/op/token_code.go b/pkg/op/token_code.go
index 155aa43..3612240 100644
--- a/pkg/op/token_code.go
+++ b/pkg/op/token_code.go
@@ -4,8 +4,8 @@ import (
"context"
"net/http"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// CodeExchange handles the OAuth 2.0 authorization_code grant, including
diff --git a/pkg/op/token_exchange.go b/pkg/op/token_exchange.go
index 00af485..fcb4468 100644
--- a/pkg/op/token_exchange.go
+++ b/pkg/op/token_exchange.go
@@ -7,8 +7,8 @@ import (
"strings"
"time"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type TokenExchangeRequest interface {
diff --git a/pkg/op/token_intospection.go b/pkg/op/token_intospection.go
index bb6a5a0..29234e1 100644
--- a/pkg/op/token_intospection.go
+++ b/pkg/op/token_intospection.go
@@ -5,8 +5,8 @@ import (
"errors"
"net/http"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type Introspector interface {
diff --git a/pkg/op/token_jwt_profile.go b/pkg/op/token_jwt_profile.go
index defb937..96ce1ed 100644
--- a/pkg/op/token_jwt_profile.go
+++ b/pkg/op/token_jwt_profile.go
@@ -5,8 +5,8 @@ import (
"net/http"
"time"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type JWTAuthorizationGrantExchanger interface {
@@ -89,7 +89,6 @@ func CreateJWTTokenResponse(ctx context.Context, tokenRequest TokenRequest, crea
AccessToken: accessToken,
TokenType: oidc.BearerToken,
ExpiresIn: uint64(validity.Seconds()),
- Scope: tokenRequest.GetScopes(),
}, nil
}
diff --git a/pkg/op/token_refresh.go b/pkg/op/token_refresh.go
index a87e883..92ef476 100644
--- a/pkg/op/token_refresh.go
+++ b/pkg/op/token_refresh.go
@@ -4,11 +4,11 @@ import (
"context"
"errors"
"net/http"
- "slices"
"time"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/strings"
)
type RefreshTokenRequest interface {
@@ -85,7 +85,7 @@ func ValidateRefreshTokenScopes(requestedScopes []string, authRequest RefreshTok
return nil
}
for _, scope := range requestedScopes {
- if !slices.Contains(authRequest.GetScopes(), scope) {
+ if !strings.Contains(authRequest.GetScopes(), scope) {
return oidc.ErrInvalidScope()
}
}
diff --git a/pkg/op/token_request.go b/pkg/op/token_request.go
index 3f5af7a..85e2270 100644
--- a/pkg/op/token_request.go
+++ b/pkg/op/token_request.go
@@ -6,8 +6,8 @@ import (
"net/http"
"net/url"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type Exchanger interface {
@@ -132,19 +132,11 @@ func AuthorizeClientIDSecret(ctx context.Context, clientID, clientSecret string,
// AuthorizeCodeChallenge authorizes a client by validating the code_verifier against the previously sent
// code_challenge of the auth request (PKCE)
func AuthorizeCodeChallenge(codeVerifier string, challenge *oidc.CodeChallenge) error {
- if challenge == nil {
- if codeVerifier != "" {
- return oidc.ErrInvalidRequest().WithDescription("code_verifier unexpectedly provided")
- }
-
- return nil
- }
-
if codeVerifier == "" {
- return oidc.ErrInvalidRequest().WithDescription("code_verifier required")
+ return oidc.ErrInvalidRequest().WithDescription("code_challenge required")
}
if !oidc.VerifyCodeChallenge(challenge, codeVerifier) {
- return oidc.ErrInvalidGrant().WithDescription("invalid code_verifier")
+ return oidc.ErrInvalidGrant().WithDescription("invalid code challenge")
}
return nil
}
diff --git a/pkg/op/token_request_test.go b/pkg/op/token_request_test.go
deleted file mode 100644
index d226af6..0000000
--- a/pkg/op/token_request_test.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package op_test
-
-import (
- "testing"
-
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
- "github.com/stretchr/testify/assert"
-)
-
-func TestAuthorizeCodeChallenge(t *testing.T) {
- tests := []struct {
- name string
- codeVerifier string
- codeChallenge *oidc.CodeChallenge
- want func(t *testing.T, err error)
- }{
- {
- name: "missing both code_verifier and code_challenge",
- codeVerifier: "",
- codeChallenge: nil,
- want: func(t *testing.T, err error) {
- assert.Nil(t, err)
- },
- },
- {
- name: "valid code_verifier",
- codeVerifier: "Hello World!",
- codeChallenge: &oidc.CodeChallenge{
- Challenge: "f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk",
- Method: oidc.CodeChallengeMethodS256,
- },
- want: func(t *testing.T, err error) {
- assert.Nil(t, err)
- },
- },
- {
- name: "invalid code_verifier",
- codeVerifier: "Hi World!",
- codeChallenge: &oidc.CodeChallenge{
- Challenge: "f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk",
- Method: oidc.CodeChallengeMethodS256,
- },
- want: func(t *testing.T, err error) {
- assert.ErrorContains(t, err, "invalid code_verifier")
- },
- },
- {
- name: "code_verifier provided without code_challenge",
- codeVerifier: "code_verifier",
- codeChallenge: nil,
- want: func(t *testing.T, err error) {
- assert.ErrorContains(t, err, "code_verifier unexpectedly provided")
- },
- },
- {
- name: "empty code_verifier",
- codeVerifier: "",
- codeChallenge: &oidc.CodeChallenge{
- Challenge: "f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk",
- Method: oidc.CodeChallengeMethodS256,
- },
- want: func(t *testing.T, err error) {
- assert.ErrorContains(t, err, "code_verifier required")
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- err := op.AuthorizeCodeChallenge(tt.codeVerifier, tt.codeChallenge)
-
- tt.want(t, err)
- })
- }
-}
diff --git a/pkg/op/token_revocation.go b/pkg/op/token_revocation.go
index 049ee15..a86a481 100644
--- a/pkg/op/token_revocation.go
+++ b/pkg/op/token_revocation.go
@@ -7,8 +7,8 @@ import (
"net/url"
"strings"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type Revoker interface {
diff --git a/pkg/op/userinfo.go b/pkg/op/userinfo.go
index ff75e72..839b139 100644
--- a/pkg/op/userinfo.go
+++ b/pkg/op/userinfo.go
@@ -6,8 +6,8 @@ import (
"net/http"
"strings"
- httphelper "git.christmann.info/LARA/zitadel-oidc/v3/pkg/http"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ httphelper "github.com/zitadel/oidc/v3/pkg/http"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type UserinfoProvider interface {
diff --git a/pkg/op/verifier_access_token.go b/pkg/op/verifier_access_token.go
index 585ca54..6ac29f2 100644
--- a/pkg/op/verifier_access_token.go
+++ b/pkg/op/verifier_access_token.go
@@ -3,7 +3,7 @@ package op
import (
"context"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type AccessTokenVerifier oidc.Verifier
diff --git a/pkg/op/verifier_access_token_example_test.go b/pkg/op/verifier_access_token_example_test.go
index b97a7fd..397a2d3 100644
--- a/pkg/op/verifier_access_token_example_test.go
+++ b/pkg/op/verifier_access_token_example_test.go
@@ -4,9 +4,9 @@ import (
"context"
"fmt"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
// MyCustomClaims extends the TokenClaims base,
diff --git a/pkg/op/verifier_access_token_test.go b/pkg/op/verifier_access_token_test.go
index 5845f9f..66e32ce 100644
--- a/pkg/op/verifier_access_token_test.go
+++ b/pkg/op/verifier_access_token_test.go
@@ -5,10 +5,10 @@ import (
"testing"
"time"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
func TestNewAccessTokenVerifier(t *testing.T) {
diff --git a/pkg/op/verifier_id_token_hint.go b/pkg/op/verifier_id_token_hint.go
index 02610aa..331c64c 100644
--- a/pkg/op/verifier_id_token_hint.go
+++ b/pkg/op/verifier_id_token_hint.go
@@ -4,7 +4,7 @@ import (
"context"
"errors"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
type IDTokenHintVerifier oidc.Verifier
diff --git a/pkg/op/verifier_id_token_hint_test.go b/pkg/op/verifier_id_token_hint_test.go
index 347e33c..597e291 100644
--- a/pkg/op/verifier_id_token_hint_test.go
+++ b/pkg/op/verifier_id_token_hint_test.go
@@ -6,10 +6,10 @@ import (
"testing"
"time"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
func TestNewIDTokenHintVerifier(t *testing.T) {
diff --git a/pkg/op/verifier_jwt_profile.go b/pkg/op/verifier_jwt_profile.go
index 85bfb14..06a7d34 100644
--- a/pkg/op/verifier_jwt_profile.go
+++ b/pkg/op/verifier_jwt_profile.go
@@ -8,7 +8,7 @@ import (
jose "github.com/go-jose/go-jose/v4"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
)
// JWTProfileVerfiier extends oidc.Verifier with
diff --git a/pkg/op/verifier_jwt_profile_test.go b/pkg/op/verifier_jwt_profile_test.go
index 2068678..d96cbb4 100644
--- a/pkg/op/verifier_jwt_profile_test.go
+++ b/pkg/op/verifier_jwt_profile_test.go
@@ -5,11 +5,11 @@ import (
"testing"
"time"
- tu "git.christmann.info/LARA/zitadel-oidc/v3/internal/testutil"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/oidc"
- "git.christmann.info/LARA/zitadel-oidc/v3/pkg/op"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ tu "github.com/zitadel/oidc/v3/internal/testutil"
+ "github.com/zitadel/oidc/v3/pkg/oidc"
+ "github.com/zitadel/oidc/v3/pkg/op"
)
func TestNewJWTProfileVerifier(t *testing.T) {
diff --git a/pkg/strings/strings.go b/pkg/strings/strings.go
index b8f43a1..af48cf3 100644
--- a/pkg/strings/strings.go
+++ b/pkg/strings/strings.go
@@ -1,9 +1,10 @@
package strings
-import "slices"
-
-// Deprecated: Use standard library [slices.Contains] instead.
func Contains(list []string, needle string) bool {
- // TODO(v4): remove package.
- return slices.Contains(list, needle)
+ for _, item := range list {
+ if item == needle {
+ return true
+ }
+ }
+ return false
}