merge main into next

This commit is contained in:
adlerhurst 2023-10-19 12:34:00 +02:00
parent b5564572bc
commit bd23a7a56f
107 changed files with 1321 additions and 554 deletions

View File

@ -30,6 +30,7 @@ jobs:
-
uses: actions/cache/restore@v3
timeout-minutes: 1
continue-on-error: true
id: cache
with:
key: console-${{ hashFiles('console', 'proto', '!console/dist') }}

View File

@ -56,6 +56,7 @@ jobs:
uses: actions/cache/restore@v3
id: cache
timeout-minutes: 1
continue-on-error: true
name: restore previous results
with:
key: integration-test-postgres-${{ inputs.core_cache_key }}

View File

@ -40,6 +40,7 @@ jobs:
uses: actions/cache/restore@v3
id: cache
timeout-minutes: 1
continue-on-error: true
name: restore previous results
with:
key: unit-test-${{ inputs.core_cache_key }}

View File

@ -41,6 +41,7 @@ jobs:
-
uses: actions/cache/restore@v3
timeout-minutes: 1
continue-on-error: true
id: cache
with:
key: core-${{ hashFiles( 'go.*', 'openapi', 'cmd', 'pkg/grpc/**/*.go', 'proto', 'internal') }}

View File

@ -83,7 +83,7 @@ console_build: console_dependencies console_client
.PHONY: clean
clean:
$(RM) .artifacts/grpc
$(RM) -r .artifacts/grpc
$(RM) $(gen_authopt_path)
$(RM) $(gen_zitadel_path)

View File

@ -103,7 +103,7 @@ COPY --from=core-assets /go/src/github.com/zitadel/zitadel/internal ./internal
# #######################################
# download console dependencies
# #######################################
FROM node:18-buster AS console-deps
FROM node:20-buster AS console-deps
WORKDIR /zitadel/console
@ -115,7 +115,7 @@ RUN yarn install --frozen-lockfile
# #######################################
# generate console client
# #######################################
FROM node:18-buster AS console-client
FROM node:20-buster AS console-client
WORKDIR /zitadel/console

View File

@ -767,7 +767,7 @@ DefaultInstance:
PreHeader: Verify email
Subject: Verify email
Greeting: Hello {{.DisplayName}},
Text: A new email has been added. Please use the button below to verify your mail. (Code {{.Code}}) If you din't add a new email, please ignore this email.
Text: A new email has been added. Please use the button below to verify your email. (Code {{.Code}}) If you din't add a new email, please ignore this email.
ButtonText: Verify email
- MessageTextType: VerifyPhone
Language: en

View File

@ -35,8 +35,8 @@ FirstInstance:
# If FirstInstance.Org.Machine.Machine is defined, a service user is created with the IAM_OWNER role, not a human user.
Machine:
Machine:
Username: # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_USERNAME
Name: # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_NAME
Username: # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME
Name: # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME
MachineKey:
# date format: 2023-01-01T00:00:00Z
ExpirationDate: # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINEKEY_EXPIRATIONDATE

View File

@ -19,7 +19,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/saml/pkg/provider"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"

View File

@ -157,7 +157,7 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
this.service
.removeMyAuthFactorOTPEmail()
.then(() => {
this.toast.showInfo('USER.TOAST.U2FREMOVED', true);
this.toast.showInfo('USER.TOAST.OTPREMOVED', true);
this.cleanupList();
this.getMFAs();
@ -169,7 +169,7 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
this.service
.removeMyAuthFactorOTPSMS()
.then(() => {
this.toast.showInfo('USER.TOAST.U2FREMOVED', true);
this.toast.showInfo('USER.TOAST.OTPREMOVED', true);
this.cleanupList();
this.getMFAs();

View File

@ -102,6 +102,36 @@ export class UserMfaComponent implements OnInit, OnDestroy {
.catch((error) => {
this.toast.showError(error);
});
} else if (factor.otpEmail) {
this.mgmtUserService
.removeHumanAuthFactorOTPEmail(this.user.id)
.then(() => {
this.toast.showInfo('USER.TOAST.OTPREMOVED', true);
const index = this.dataSource.data.findIndex((mfa) => !!mfa.otpEmail);
if (index > -1) {
this.dataSource.data.splice(index, 1);
}
this.getMFAs();
})
.catch((error) => {
this.toast.showError(error);
});
} else if (factor.otpSms) {
this.mgmtUserService
.removeHumanAuthFactorOTPSMS(this.user.id)
.then(() => {
this.toast.showInfo('USER.TOAST.OTPREMOVED', true);
const index = this.dataSource.data.findIndex((mfa) => !!mfa.otpSms);
if (index > -1) {
this.dataSource.data.splice(index, 1);
}
this.getMFAs();
})
.catch((error) => {
this.toast.showError(error);
});
}
}
});

View File

@ -322,8 +322,12 @@ import {
RemoveCustomLabelPolicyLogoDarkResponse,
RemoveCustomLabelPolicyLogoRequest,
RemoveCustomLabelPolicyLogoResponse,
RemoveHumanAuthFactorOTPEmailRequest,
RemoveHumanAuthFactorOTPEmailResponse,
RemoveHumanAuthFactorOTPRequest,
RemoveHumanAuthFactorOTPResponse,
RemoveHumanAuthFactorOTPSMSRequest,
RemoveHumanAuthFactorOTPSMSResponse,
RemoveHumanAuthFactorU2FRequest,
RemoveHumanAuthFactorU2FResponse,
RemoveHumanLinkedIDPRequest,
@ -1805,6 +1809,18 @@ export class ManagementService {
return this.grpcService.mgmt.removeHumanAuthFactorU2F(req, null).then((resp) => resp.toObject());
}
public removeHumanAuthFactorOTPSMS(userId: string): Promise<RemoveHumanAuthFactorOTPSMSResponse.AsObject> {
const req = new RemoveHumanAuthFactorOTPSMSRequest();
req.setUserId(userId);
return this.grpcService.mgmt.removeHumanAuthFactorOTPSMS(req, null).then((resp) => resp.toObject());
}
public removeHumanAuthFactorOTPEmail(userId: string): Promise<RemoveHumanAuthFactorOTPEmailResponse.AsObject> {
const req = new RemoveHumanAuthFactorOTPEmailRequest();
req.setUserId(userId);
return this.grpcService.mgmt.removeHumanAuthFactorOTPEmail(req, null).then((resp) => resp.toObject());
}
public updateHumanProfile(
userId: string,
firstName?: string,

View File

@ -51,3 +51,58 @@ The object has the following fields and methods:
Returns the body as JSON object, or throws an error if the body is not a json object.
- `text()` *string*
Returns the body
## UUID
This module provides functionality to generate a UUID
### Import
```js
let uuid = require("zitadel/uuid")
```
### `uuid.vX()` function
This function generates a UUID using [google/uuid](https://github.com/google/uuid). `vX` allows to define the UUID version:
- `uuid.v1()` *string*
Generates a UUID version 1, based on date-time and MAC address
- `uuid.v3(namespace, data)` *string*
Generates a UUID version 3, based on the provided namespace using MD5
- `uuid.v4()` *string*
Generates a UUID version 4, which is randomly generated
- `uuid.v5(namespace, data)` *string*
Generates a UUID version 5, based on the provided namespace using SHA1
#### Parameters
- `namespace` *UUID*/*string*
Namespace to be used in the hashing function. Either provide one of defined [namespaces](#namespaces) or a string representing a UUID.
- `data` *[]byte*/*string*
data to be used in the hashing function. Possible types are []byte or string.
### Namespaces
The following predefined namespaces can be used for `uuid.v3` and `uuid.v5`:
- `uuid.namespaceDNS` *UUID*
6ba7b810-9dad-11d1-80b4-00c04fd430c8
- `uuid.namespaceURL` *UUID*
6ba7b811-9dad-11d1-80b4-00c04fd430c8
- `uuid.namespaceOID` *UUID*
6ba7b812-9dad-11d1-80b4-00c04fd430c8
- `uuid.namespaceX500` *UUID*
6ba7b814-9dad-11d1-80b4-00c04fd430c8
### Example
```js
let uuid = require("zitadel/uuid")
function setUUID(ctx, api) {
if (api.metadata === undefined) {
return;
}
api.v1.user.appendMetadata('custom-id', uuid.v4());
}
```

View File

@ -0,0 +1,87 @@
---
title: Description of onboarding support services for ZITADEL
sidebar_label: Onboarding support
custom_edit_url: null
---
This annex of the [Framework Agreement](terms-of-service) describes the onboarding support services offered by us for our services.
Last revised: October 12, 2023
Our onboarding support should help you, as a new customer, to get a better understanding on how to integrate ZITADEL into your solution, how to tackle the migration, and ensure a highly-available day-to-day operation.
Onboarding support services can be offered to customers that enter a ZITADEL Cloud or a ZITADEL Enterprise subscription.
If you intend to use the open source version exclusively then please join our community chat or Github.
Your questions might help other people in the community and will make our project better over time.
Please [contact us](https://zitadel.com/contact) for a quote and to get started with onboarding support.
Below you will find topics covered and scope of the offered services.
## Proof of value
Within a short time-frame, f.e. 3 weeks, we can show the value of using our services and have the ability to establish the proof a of working setup for your most critical use cases.
We may offer to support you during an initial period to evaluate next steps.
Before the start of the period we may ask you to provide a description of your critical use cases and a high-level overview of your planned integration architecture.
During this period you should make sure that you have the necessary resources on your side to complete the proof of value.
## Onboarding term
With the onboarding support we provide the initial knowledge transfer to configure and operate ZITADEL.
During the term you will get direct access to our engineering team via [Technical Account Management](./support-services.md#technical-account-manager).
Duration is typically 3 months but this could vary depending on your requirements.
We offer an onboarding term in combination with ZITADEL Enterprise subscriptions.
### Topics covered
Topics of the onboarding term may include:
- Administration
- DevOps (Operation)
- Architecture
- Integration
- Migration
- Security Best Practices & Go-Live Checkup
The scope will be tailored to your requirements.
More details
- IAM Configuration
- Walk-though all features
- Users / Manuals
- Authentication & Management APIs
- Validation of tokens
- Client integration best-practices
- Event types
- Database schemas and compute models
- Accessing database
- Observability (Logs, Errors, Metrics, Tracing)
- Operations best practices (Deployment, Backup, Networking etc.)
- Check prerequisites and architecture
- Troubleshoot installation and configuration of ZITADEL
- Troubleshoot and configuration connectivity to the database
- Functional testing of the ZITADEL instance
<details>
<summary>Out of scope</summary>
<ul>
<li>Performance testing</li>
<li>Setting up or maintaining backup storage</li>
<li>Running multiple ZITADEL instances on the same cluster</li>
<li>Integration into internal monitoring and alerting</li>
<li>Multi-cluster architecture deployments</li>
<li>DNS, Network and Firewall configuration</li>
<li>Customer-specific Kubernetes configuration needs</li>
<li>Non-production environments</li>
<li>Production deployment</li>
<li>Application-side coding, configuration, or tuning</li>
</ul>
</details>
## Continuous support
After the onboarding phase has ended we will provide continuous support according to your subscription.
We can provide you with continued access to the technical account management in our Enterprise subscriptions.

View File

@ -10,7 +10,7 @@ This annex of the [Framework Agreement](terms-of-service) and the [Support Servi
Support Services for products and services provided by ZITADEL is offered to customers according to the terms and conditions outlined in this document.
The customer may purchase support services from ZITADEL (CAOS Ltd.) directly.
Last revised: March 15, 2023
Last revised: October 6, 2023
## Support Services
@ -82,7 +82,8 @@ Phone Support | +41 43 215 27 34
ZITADEL will enhance its support offering by providing eligible clients with a Technical Account Manager (TAM), who will perform the following tasks for up to the specified amount of time per week during the term of service:
- Provide support and advice regarding best practices on platform, product and configuration covered by the applicable Support Services;
- Participate in review calls every other week at mutually agreed times addressing customers operational issues.
- Participate in review calls every other week at mutually agreed times addressing customers operational challenges or complex support requests;
- Walk-through of new features and customer feedback.
We offer TAM services only bundled with specific subscription plans, and the option to add more TAM hours to these plans.
If you require consulting for your projects, please request a quote via our [website](https://zitadel.com/contact).

View File

@ -1,36 +0,0 @@
---
title: Application Support Trainings
---
## ZITADEL DevOps
In this session your second level support and operations team will gain an understanding on how to extract relevant information for technical support questions and root cause analysis. We will also present our DevOps best practices and answer your questions.
**Audience**: 2nd Level Support Staff, Operations
**Duration**: 0.5 day
**Topics covered**:
- Event types
- Database schemas and compute models
- Accessing database
- Observability (Logs, Errors, Metrics, Tracing)
- Operations best practices (Deployment, Backup, Networking etc.)
- Q&A
## ZITADEL Administrator
In this hands-on training your employees will get a complete overview of the system and learn how to configure and use ZITADEL. Your support staff will gain the required knowledge to provide user-support, while your solution owners gain an understanding about integration of clients.
**Audience**: 1st / 2nd Level Support Staff, Solution Owner, QA Manager (optional)
**Duration**: 0.5 days
**Topics covered**:
- IAM Configuration
- Walk-though all features
- Users / Manuals
- APIs
- Validation of tokens
- Client integration best-practices
- Q&A

View File

@ -1,30 +0,0 @@
---
title: ZITADEL Trainings
sidebar_label: Introduction
---
The following pages describe the the trainings provided by ZITADEL. These trainings are intended for onboarding and during the course of a Support Program.
Training should be held as block-sessions with the relevant staff from your organization.
## Onboarding Project
You receive professional onboarding support from our engineers, who help you to setup and configure ZITADEL on your infrastructure.
[More information](project)
## Application Support Trainings
With the application support trainings we provide the initial knowledge transfer to manage and support ZITADEL. The trainings are held as block-sessions with relevant staff from your organization. Prices are flat-fee, excl. expenses.
* [ZITADEL DevOps](application#zitadel-devops)
* [ZITADEL Administrator](application#zitadel-administrator)
## Recurring Trainings
While you can benefit from a technical account manager during your term, these trainings are designed to onboard new staff or update staff about larger changes to the platform. Prices are flat-fee, excl. expenses.
* [ZITADEL Support Refresher](recurring#zitadel-support-refresher)
* [ZITADEL Support Onboarding](recurring#zitadel-support-onboarding)
In case you have any questions please [get in touch](https://zitadel.com/contact).

View File

@ -1,35 +0,0 @@
---
title: Onboarding Project
---
Effort required during depends on the complexity of your infrastructure and the overall setup. With a Multi-Zone Setup (excl. Multi-Region), support during this phase requires around 10-25h over 2 weeks. Actual effort is based on time and material.
Scope of the project is agreed on individual basis.
## In Scope
- Check prerequisites and architecture
- Troubleshoot installation and configuration of ZITADEL
- Troubleshoot and configuration connectivity to the database
- Functional testing of the ZITADEL instance
## Out of Scope
- Running multiple ZITADEL instances on the same cluster
- Integration into internal monitoring and alerting
- Multi-cluster architecture deployments
- DNS, Network and Firewall configuration
- Customer-specific Kubernetes configuration needs
- Changes for specific environments
- Performance testing
- Production deployment
- Application-side coding, configuration, or tuning
- Changes or configuration on assets used in ZITADEL
- Setting up or maintaining backup storage
## Prerequisites
- Running Kubernetes with possibility to deploy to namespaces
- Inbound and outbound HTTP/2 traffic possible
- For being able to send SMS, we need a Twilio sender name, SID and an auth token
- ZITADEL also needs to connect to an email relay of your choice. We need the SMTP host, user and app key as well as the ZITADEL emails sender address and name.

View File

@ -1,33 +0,0 @@
---
title: Recurring Trainings
---
## ZITADEL Support Refresher
In this session you can refresh knowledge about existing and gain experience with new features of ZITADEL to keep the quality of your support high. We recommend an half day training per support staff.
**Audience**: 1st / 2nd Level Support Staff, Solution Owner, QA Manager (optional)
**Duration**: 0.5 day / support staff
**Topics covered**:
* Walk-through new features
* Review of difficult support issues
* Review of customer feedback
* Q&A
## ZITADEL Support Onboarding
In this hands-on training new support staff will get an overview of the system and learn how to configure and use ZITADEL to provide support for users.
**Audience**: 1st / 2nd Level Support Staff, Solution Owner, QA Manager (optional)
**Duration**: 0.5 days / support staff
**Topics covered**:
* Event types
* Accessing database
* Logs and Errors
* Validation of tokens
* Walk-through key features
* Q&A

View File

@ -425,6 +425,11 @@ module.exports = {
items: [
"support/software-release-cycles-support",
"support/troubleshooting",
{
type: 'link',
label: 'Support Service Descriptions',
href: '/legal/support-services',
},
{
type: 'category',
label: "Technical Advisory",
@ -440,17 +445,6 @@ module.exports = {
},
],
},
{
type: "category",
label: "Trainings",
collapsed: true,
items: [
"support/trainings/introduction",
"support/trainings/application",
"support/trainings/recurring",
"support/trainings/project",
],
},
]
},
],
@ -697,6 +691,7 @@ module.exports = {
"legal/cloud-service-description",
"legal/service-level-description",
"legal/support-services",
"legal/onboarding-support",
],
},
{

30
go.mod
View File

@ -22,6 +22,7 @@ require (
github.com/drone/envsubst v1.0.3
github.com/envoyproxy/protoc-gen-validate v1.0.2
github.com/fatih/color v1.15.0
github.com/go-jose/go-jose/v3 v3.0.0
github.com/go-ldap/ldap/v3 v3.4.5
github.com/go-webauthn/webauthn v0.8.6
github.com/golang/mock v1.6.0
@ -48,11 +49,12 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/muesli/gamut v0.3.1
github.com/muhlemmer/gu v0.3.1
github.com/muhlemmer/httpforwarded v0.1.0
github.com/nicksnyder/go-i18n/v2 v2.2.1
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.4.0
github.com/rakyll/statik v0.1.7
github.com/rs/cors v1.10.0
github.com/rs/cors v1.10.1
github.com/sony/sonyflake v1.2.0
github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.16.0
@ -60,36 +62,35 @@ require (
github.com/superseriousbusiness/exifremove v0.0.0-20210330092427-6acd27eac203
github.com/ttacon/libphonenumber v1.2.1
github.com/zitadel/logging v0.4.0
github.com/zitadel/oidc/v2 v2.11.0
github.com/zitadel/oidc/v3 v3.0.2
github.com/zitadel/passwap v0.4.0
github.com/zitadel/saml v0.1.2
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.43.0
go.opentelemetry.io/otel v1.17.0
go.opentelemetry.io/otel v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0
go.opentelemetry.io/otel/exporters/prometheus v0.40.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0
go.opentelemetry.io/otel/metric v1.17.0
go.opentelemetry.io/otel/metric v1.19.0
go.opentelemetry.io/otel/sdk v1.17.0
go.opentelemetry.io/otel/sdk/metric v0.40.0
go.opentelemetry.io/otel/trace v1.17.0
golang.org/x/crypto v0.13.0
golang.org/x/net v0.15.0
golang.org/x/oauth2 v0.12.0
go.opentelemetry.io/otel/trace v1.19.0
golang.org/x/crypto v0.14.0
golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.13.0
golang.org/x/sync v0.3.0
golang.org/x/text v0.13.0
google.golang.org/api v0.138.0
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
gopkg.in/square/go-jose.v2 v2.6.0
sigs.k8s.io/yaml v1.3.0
)
require (
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.43.1 // indirect
github.com/crewjam/httperr v0.2.0 // indirect
github.com/dmarkham/enumer v1.5.8 // indirect
github.com/go-chi/chi/v5 v5.0.10 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
@ -105,14 +106,11 @@ require (
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/muhlemmer/httpforwarded v0.1.0 // indirect
github.com/pascaldekloe/name v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/smartystreets/assertions v1.0.0 // indirect
github.com/zenazn/goji v1.0.1 // indirect
github.com/zitadel/schema v1.3.0 // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
)
@ -154,7 +152,7 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/google/uuid v1.3.1
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
@ -203,7 +201,7 @@ require (
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
golang.org/x/sys v0.12.0
golang.org/x/sys v0.13.0
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect

53
go.sum
View File

@ -184,8 +184,6 @@ github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwu
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dmarkham/enumer v1.5.8 h1:fIF11F9l5jyD++YYvxcSH5WgHfeaSGPaN/T4kOQ4qEM=
github.com/dmarkham/enumer v1.5.8/go.mod h1:d10o8R3t/gROm2p3BXqTkMt2+HMuxEmWCXzorAruYak=
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/dop251/goja v0.0.0-20230531210528-d7324b2d74f7/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
github.com/dop251/goja v0.0.0-20230828202809-3dbe69dd2b8e h1:UvQD6hTSfeM6hhTQ24Dlw2RppP05W7SWbWb6kubJAog=
@ -267,6 +265,8 @@ github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
@ -275,6 +275,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
@ -720,8 +722,6 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/name v1.0.0 h1:n7LKFgHixETzxpRv2R77YgPUFo85QHGZKrdaYm7eY5U=
github.com/pascaldekloe/name v1.0.0/go.mod h1:Z//MfYJnH4jVpQ9wkclwu2I2MkHmXTlT9wR5UZScttM=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
@ -782,8 +782,8 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8=
github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
@ -883,12 +883,14 @@ github.com/zenazn/goji v1.0.1 h1:4lbD8Mx2h7IvloP7r2C0D6ltZP6Ufip8Hn0wmSK5LR8=
github.com/zenazn/goji v1.0.1/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
github.com/zitadel/logging v0.4.0 h1:lRAIFgaRoJpLNbsL7jtIYHcMDoEJP9QZB4GqMfl4xaA=
github.com/zitadel/logging v0.4.0/go.mod h1:6uALRJawpkkuUPCkgzfgcPR3c2N908wqnOnIrRelUFc=
github.com/zitadel/oidc/v2 v2.11.0 h1:Am4/yQr4iiM5bznRgF3FOp+wLdKx2gzSU73uyI9vvBE=
github.com/zitadel/oidc/v2 v2.11.0/go.mod h1:enFSVBQI6aE0TEB1ntjXs9r6O6DEosxX4uhEBLBVD8o=
github.com/zitadel/oidc/v3 v3.0.2 h1:fw0EAjx8lIlDMJ54hDz2fWIhpW/Y13tW5gd1qWGqbr4=
github.com/zitadel/oidc/v3 v3.0.2/go.mod h1:ne9V9FHug4iUZDV42JirWVLHcbmwaxY8LnkcfekHgRg=
github.com/zitadel/passwap v0.4.0 h1:cMaISx+Ve7ilgG7Q8xOli4Z6IWr8Gndss+jeBk5A3O0=
github.com/zitadel/passwap v0.4.0/go.mod h1:yHaDM4A68yRkdic5BZ4iUNoc19hT+kYt8n1/Nz+I87g=
github.com/zitadel/saml v0.1.2 h1:RICwNTuP2upX4A1sZ8iq1rv4/x3DhZHzFx1e5bTKoTo=
github.com/zitadel/saml v0.1.2/go.mod h1:M+X+3vMUulpoLofKeH/W1/qjQQ3owitc2GuGDu3oYpM=
github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0=
github.com/zitadel/schema v1.3.0/go.mod h1:NptN6mkBDFvERUCvZHlvWmmME+gmZ44xzwRXwhzsbtc=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -905,8 +907,8 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.4
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0/go.mod h1:1WpsUwjQrUJSNugfMlPn0rPRJ9Do7wwBgTBPK7MLiS4=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.43.0 h1:HKORGpiOY0R0nAPtKx/ub8/7XoHhRooP8yNRkuPfelI=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.43.0/go.mod h1:e+y1M74SYXo/FcIx3UATwth2+5dDkM8dBi7eXg1tbw8=
go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM=
go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0 h1:U5GYackKpVKlPrd/5gKMlrTlP2dCESAAFU682VCpieY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0/go.mod h1:aFsJfCEnLzEu9vRRAcUiB/cpRTbVsNdF3OHSPpdjxZQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0 h1:iGeIsSYwpYSvh5UGzWrJfTDJvPjrXtxl3GUppj6IXQU=
@ -915,14 +917,14 @@ go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ER
go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 h1:Ut6hgtYcASHwCzRHkXEtSsM251cXJPW+Z9DyLwEn6iI=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0/go.mod h1:TYeE+8d5CjrgBa0ZuRaDeMpIC1xZ7atg4g+nInjuSjc=
go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc=
go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE=
go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ=
go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU=
go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs=
go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ=
go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
@ -952,6 +954,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -965,8 +968,8 @@ golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1007,8 +1010,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1059,8 +1060,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1070,8 +1071,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1154,8 +1155,8 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1242,8 +1243,6 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1384,8 +1383,6 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=

View File

@ -0,0 +1,83 @@
package actions
import (
"context"
"github.com/dop251/goja"
"github.com/google/uuid"
"github.com/zitadel/logging"
)
func WithUUID(ctx context.Context) Option {
return func(c *runConfig) {
c.modules["zitadel/uuid"] = func(runtime *goja.Runtime, module *goja.Object) {
requireUUID(ctx, runtime, module)
}
}
}
func requireUUID(_ context.Context, runtime *goja.Runtime, module *goja.Object) {
o := module.Get("exports").(*goja.Object)
logging.OnError(o.Set("v1", inRuntime(uuid.NewUUID, runtime))).Warn("unable to set module")
logging.OnError(o.Set("v3", inRuntimeHash(uuid.NewMD5, runtime))).Warn("unable to set module")
logging.OnError(o.Set("v4", inRuntime(uuid.NewRandom, runtime))).Warn("unable to set module")
logging.OnError(o.Set("v5", inRuntimeHash(uuid.NewSHA1, runtime))).Warn("unable to set module")
logging.OnError(o.Set("namespaceDNS", uuid.NameSpaceDNS)).Warn("unable to set namespace")
logging.OnError(o.Set("namespaceURL", uuid.NameSpaceURL)).Warn("unable to set namespace")
logging.OnError(o.Set("namespaceOID", uuid.NameSpaceOID)).Warn("unable to set namespace")
logging.OnError(o.Set("namespaceX500", uuid.NameSpaceX500)).Warn("unable to set namespace")
}
func inRuntime(function func() (uuid.UUID, error), runtime *goja.Runtime) func(call goja.FunctionCall) goja.Value {
return func(call goja.FunctionCall) goja.Value {
if len(call.Arguments) != 0 {
panic("invalid arg count")
}
uuid, err := function()
if err != nil {
logging.WithError(err)
panic(err)
}
return runtime.ToValue(uuid.String())
}
}
func inRuntimeHash(function func(uuid.UUID, []byte) uuid.UUID, runtime *goja.Runtime) func(call goja.FunctionCall) goja.Value {
return func(call goja.FunctionCall) goja.Value {
if len(call.Arguments) != 2 {
logging.WithFields("count", len(call.Arguments)).Debug("other than 2 args provided")
panic("invalid arg count")
}
var err error
var namespace uuid.UUID
switch n := call.Arguments[0].Export().(type) {
case string:
namespace, err = uuid.Parse(n)
if err != nil {
logging.WithError(err).Debug("namespace failed parsing as UUID")
panic(err)
}
case uuid.UUID:
namespace = n
default:
logging.WithError(err).Debug("invalid type for namespace")
panic(err)
}
var data []byte
switch d := call.Arguments[1].Export().(type) {
case string:
data = []byte(d)
case []byte:
data = d
default:
logging.WithError(err).Debug("invalid type for data")
panic(err)
}
return runtime.ToValue(function(namespace, data).String())
}
}

View File

@ -10,8 +10,8 @@ import (
"sync"
"time"
"github.com/zitadel/oidc/v2/pkg/op"
"gopkg.in/square/go-jose.v2"
"github.com/go-jose/go-jose/v3"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/crypto"
caos_errs "github.com/zitadel/zitadel/internal/errors"
@ -28,7 +28,7 @@ type TokenVerifier struct {
authZRepo authZRepo
clients sync.Map
authMethods MethodMapping
systemJWTProfile op.JWTProfileVerifier
systemJWTProfile *op.JWTProfileVerifier
}
type MembershipsResolver interface {

View File

@ -3,7 +3,7 @@ package management
import (
"context"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/http"

View File

@ -4,7 +4,7 @@ import (
"context"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/text/language"
"google.golang.org/protobuf/types/known/durationpb"
@ -647,6 +647,26 @@ func (s *Server) RemoveHumanAuthFactorU2F(ctx context.Context, req *mgmt_pb.Remo
}, nil
}
func (s *Server) RemoveHumanAuthFactorOTPSMS(ctx context.Context, req *mgmt_pb.RemoveHumanAuthFactorOTPSMSRequest) (*mgmt_pb.RemoveHumanAuthFactorOTPSMSResponse, error) {
objectDetails, err := s.command.RemoveHumanOTPSMS(ctx, req.UserId, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
return &mgmt_pb.RemoveHumanAuthFactorOTPSMSResponse{
Details: obj_grpc.DomainToChangeDetailsPb(objectDetails),
}, nil
}
func (s *Server) RemoveHumanAuthFactorOTPEmail(ctx context.Context, req *mgmt_pb.RemoveHumanAuthFactorOTPEmailRequest) (*mgmt_pb.RemoveHumanAuthFactorOTPEmailResponse, error) {
objectDetails, err := s.command.RemoveHumanOTPEmail(ctx, req.UserId, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
return &mgmt_pb.RemoveHumanAuthFactorOTPEmailResponse{
Details: obj_grpc.DomainToChangeDetailsPb(objectDetails),
}, nil
}
func (s *Server) ListHumanPasswordless(ctx context.Context, req *mgmt_pb.ListHumanPasswordlessRequest) (*mgmt_pb.ListHumanPasswordlessResponse, error) {
query := new(query.UserAuthMethodSearchQueries)
err := query.AppendUserIDQuery(req.UserId)

View File

@ -4,7 +4,7 @@ import (
"context"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/op"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/timestamppb"

View File

@ -54,7 +54,7 @@ func TestServer_GetAuthRequest(t *testing.T) {
require.NoError(t, err)
client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
require.NoError(t, err)
authRequestID, err := Tester.CreateOIDCAuthRequest(client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
require.NoError(t, err)
now := time.Now()
@ -134,7 +134,7 @@ func TestServer_CreateCallback(t *testing.T) {
name: "session not found",
req: &oidc_pb.CreateCallbackRequest{
AuthRequestId: func() string {
authRequestID, err := Tester.CreateOIDCAuthRequest(client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
require.NoError(t, err)
return authRequestID
}(),
@ -151,7 +151,7 @@ func TestServer_CreateCallback(t *testing.T) {
name: "session token invalid",
req: &oidc_pb.CreateCallbackRequest{
AuthRequestId: func() string {
authRequestID, err := Tester.CreateOIDCAuthRequest(client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
require.NoError(t, err)
return authRequestID
}(),
@ -168,7 +168,7 @@ func TestServer_CreateCallback(t *testing.T) {
name: "fail callback",
req: &oidc_pb.CreateCallbackRequest{
AuthRequestId: func() string {
authRequestID, err := Tester.CreateOIDCAuthRequest(client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
require.NoError(t, err)
return authRequestID
}(),
@ -192,7 +192,7 @@ func TestServer_CreateCallback(t *testing.T) {
name: "code callback",
req: &oidc_pb.CreateCallbackRequest{
AuthRequestId: func() string {
authRequestID, err := Tester.CreateOIDCAuthRequest(client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
require.NoError(t, err)
return authRequestID
}(),
@ -217,7 +217,7 @@ func TestServer_CreateCallback(t *testing.T) {
AuthRequestId: func() string {
client, err := Tester.CreateOIDCImplicitFlowClient(CTX, redirectURIImplicit)
require.NoError(t, err)
authRequestID, err := Tester.CreateOIDCAuthRequestImplicit(client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURIImplicit)
authRequestID, err := Tester.CreateOIDCAuthRequestImplicit(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURIImplicit)
require.NoError(t, err)
return authRequestID
}(),

View File

@ -1,7 +1,7 @@
package oidc
import (
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/op"
"google.golang.org/grpc"
"github.com/zitadel/zitadel/internal/api/authz"

View File

@ -33,12 +33,7 @@ func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
return nil, status.Error(codes.Unauthenticated, "auth header missing")
}
var orgDomain string
orgID := grpc_util.GetHeader(authCtx, http.ZitadelOrgID)
if o, ok := req.(OrganisationFromRequest); ok {
orgID = o.OrganisationFromRequest().ID
orgDomain = o.OrganisationFromRequest().Domain
}
orgID, orgDomain := orgIDAndDomainFromRequest(authCtx, req)
ctxSetter, err := authz.CheckUserAuthorization(authCtx, req, authToken, orgID, orgDomain, verifier, authConfig, authOpt, info.FullMethod)
if err != nil {
return nil, err
@ -47,11 +42,38 @@ func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
return handler(ctxSetter(ctx), req)
}
type OrganisationFromRequest interface {
OrganisationFromRequest() *Organisation
func orgIDAndDomainFromRequest(ctx context.Context, req interface{}) (id, domain string) {
orgID := grpc_util.GetHeader(ctx, http.ZitadelOrgID)
o, ok := req.(OrganizationFromRequest)
if !ok {
return orgID, ""
}
id = o.OrganizationFromRequest().ID
domain = o.OrganizationFromRequest().Domain
if id != "" || domain != "" {
return id, domain
}
// check if the deprecated organisation is used.
// to be removed before going GA (https://github.com/zitadel/zitadel/issues/6718)
id = o.OrganisationFromRequest().ID
domain = o.OrganisationFromRequest().Domain
if id != "" || domain != "" {
return id, domain
}
return orgID, domain
}
type Organisation struct {
// Deprecated: will be removed in favor of OrganizationFromRequest (https://github.com/zitadel/zitadel/issues/6718)
type OrganisationFromRequest interface {
OrganisationFromRequest() *Organization
}
type Organization struct {
ID string
Domain string
}
type OrganizationFromRequest interface {
OrganizationFromRequest() *Organization
OrganisationFromRequest
}

View File

@ -2,10 +2,13 @@ package session
import (
"context"
"net"
"net/http"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/muhlemmer/gu"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
"github.com/zitadel/zitadel/internal/command"
@ -41,7 +44,7 @@ func (s *Server) ListSessions(ctx context.Context, req *session.ListSessionsRequ
}
func (s *Server) CreateSession(ctx context.Context, req *session.CreateSessionRequest) (*session.CreateSessionResponse, error) {
checks, metadata, err := s.createSessionRequestToCommand(ctx, req)
checks, metadata, userAgent, err := s.createSessionRequestToCommand(ctx, req)
if err != nil {
return nil, err
}
@ -50,7 +53,7 @@ func (s *Server) CreateSession(ctx context.Context, req *session.CreateSessionRe
return nil, err
}
set, err := s.command.CreateSession(ctx, cmds, metadata)
set, err := s.command.CreateSession(ctx, cmds, metadata, userAgent)
if err != nil {
return nil, err
}
@ -113,9 +116,34 @@ func sessionToPb(s *query.Session) *session.Session {
Sequence: s.Sequence,
Factors: factorsToPb(s),
Metadata: s.Metadata,
UserAgent: userAgentToPb(s.UserAgent),
}
}
func userAgentToPb(ua domain.UserAgent) *session.UserAgent {
if ua.IsEmpty() {
return nil
}
out := &session.UserAgent{
FingerprintId: ua.FingerprintID,
Description: ua.Description,
}
if ua.IP != nil {
out.Ip = gu.Ptr(ua.IP.String())
}
if ua.Header == nil {
return out
}
out.Header = make(map[string]*session.UserAgent_HeaderValues, len(ua.Header))
for k, v := range ua.Header {
out.Header[k] = &session.UserAgent_HeaderValues{
Values: v,
}
}
return out
}
func factorsToPb(s *query.Session) *session.Factors {
user := userFactorToPb(s.UserFactor)
if user == nil {
@ -188,6 +216,7 @@ func userFactorToPb(factor query.SessionUserFactor) *session.UserFactor {
LoginName: factor.LoginName,
DisplayName: factor.DisplayName,
OrganisationId: factor.ResourceOwner,
OrganizationId: factor.ResourceOwner,
}
}
@ -236,12 +265,30 @@ func idsQueryToQuery(q *session.IDsQuery) (query.SearchQuery, error) {
return query.NewSessionIDsSearchQuery(q.Ids)
}
func (s *Server) createSessionRequestToCommand(ctx context.Context, req *session.CreateSessionRequest) ([]command.SessionCommand, map[string][]byte, error) {
func (s *Server) createSessionRequestToCommand(ctx context.Context, req *session.CreateSessionRequest) ([]command.SessionCommand, map[string][]byte, *domain.UserAgent, error) {
checks, err := s.checksToCommand(ctx, req.Checks)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
return checks, req.GetMetadata(), nil
return checks, req.GetMetadata(), userAgentToCommand(req.GetUserAgent()), nil
}
func userAgentToCommand(userAgent *session.UserAgent) *domain.UserAgent {
if userAgent == nil {
return nil
}
out := &domain.UserAgent{
FingerprintID: userAgent.FingerprintId,
IP: net.ParseIP(userAgent.GetIp()),
Description: userAgent.Description,
}
if len(userAgent.Header) > 0 {
out.Header = make(http.Header, len(userAgent.Header))
for k, values := range userAgent.Header {
out.Header[k] = values.GetValues()
}
}
return out
}
func (s *Server) setSessionRequestToCommand(ctx context.Context, req *session.SetSessionRequest) ([]command.SessionCommand, error) {

View File

@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/proto"
"github.com/zitadel/zitadel/internal/integration"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
@ -53,7 +54,7 @@ func TestMain(m *testing.M) {
}())
}
func verifyCurrentSession(t testing.TB, id, token string, sequence uint64, window time.Duration, metadata map[string][]byte, factors ...wantFactor) *session.Session {
func verifyCurrentSession(t testing.TB, id, token string, sequence uint64, window time.Duration, metadata map[string][]byte, userAgent *session.UserAgent, factors ...wantFactor) *session.Session {
t.Helper()
require.NotEmpty(t, id)
require.NotEmpty(t, token)
@ -70,6 +71,11 @@ func verifyCurrentSession(t testing.TB, id, token string, sequence uint64, windo
assert.WithinRange(t, s.GetChangeDate().AsTime(), time.Now().Add(-window), time.Now().Add(window))
assert.Equal(t, sequence, s.GetSequence())
assert.Equal(t, metadata, s.GetMetadata())
if !proto.Equal(userAgent, s.GetUserAgent()) {
t.Errorf("user agent =\n%v\nwant\n%v", s.GetUserAgent(), userAgent)
}
verifyFactors(t, s.GetFactors(), window, factors)
return s
}
@ -131,11 +137,12 @@ func verifyFactors(t testing.TB, factors *session.Factors, window time.Duration,
func TestServer_CreateSession(t *testing.T) {
tests := []struct {
name string
req *session.CreateSessionRequest
want *session.CreateSessionResponse
wantErr bool
wantFactors []wantFactor
name string
req *session.CreateSessionRequest
want *session.CreateSessionResponse
wantErr bool
wantFactors []wantFactor
wantUserAgent *session.UserAgent
}{
{
name: "empty session",
@ -148,6 +155,33 @@ func TestServer_CreateSession(t *testing.T) {
},
},
},
{
name: "user agent",
req: &session.CreateSessionRequest{
Metadata: map[string][]byte{"foo": []byte("bar")},
UserAgent: &session.UserAgent{
FingerprintId: gu.Ptr("fingerPrintID"),
Ip: gu.Ptr("1.2.3.4"),
Description: gu.Ptr("Description"),
Header: map[string]*session.UserAgent_HeaderValues{
"foo": {Values: []string{"foo", "bar"}},
},
},
},
want: &session.CreateSessionResponse{
Details: &object.Details{
ResourceOwner: Tester.Organisation.ID,
},
},
wantUserAgent: &session.UserAgent{
FingerprintId: gu.Ptr("fingerPrintID"),
Ip: gu.Ptr("1.2.3.4"),
Description: gu.Ptr("Description"),
Header: map[string]*session.UserAgent_HeaderValues{
"foo": {Values: []string{"foo", "bar"}},
},
},
},
{
name: "with user",
req: &session.CreateSessionRequest{
@ -219,7 +253,7 @@ func TestServer_CreateSession(t *testing.T) {
require.NoError(t, err)
integration.AssertDetails(t, tt.want, got)
verifyCurrentSession(t, got.GetSessionId(), got.GetSessionToken(), got.GetDetails().GetSequence(), time.Minute, tt.req.GetMetadata(), tt.wantFactors...)
verifyCurrentSession(t, got.GetSessionId(), got.GetSessionToken(), got.GetDetails().GetSequence(), time.Minute, tt.req.GetMetadata(), tt.wantUserAgent, tt.wantFactors...)
})
}
}
@ -242,7 +276,7 @@ func TestServer_CreateSession_webauthn(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil, nil)
assertionData, err := Tester.WebAuthN.CreateAssertionResponse(createResp.GetChallenges().GetWebAuthN().GetPublicKeyCredentialRequestOptions(), true)
require.NoError(t, err)
@ -258,7 +292,7 @@ func TestServer_CreateSession_webauthn(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), updateResp.GetSessionToken(), updateResp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantWebAuthNFactorUserVerified)
verifyCurrentSession(t, createResp.GetSessionId(), updateResp.GetSessionToken(), updateResp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantWebAuthNFactorUserVerified)
}
func TestServer_CreateSession_successfulIntent(t *testing.T) {
@ -274,7 +308,7 @@ func TestServer_CreateSession_successfulIntent(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil, nil)
intentID, token, _, _ := Tester.CreateSuccessfulOAuthIntent(t, idpID, User.GetUserId(), "id")
updateResp, err := Client.SetSession(CTX, &session.SetSessionRequest{
@ -288,7 +322,7 @@ func TestServer_CreateSession_successfulIntent(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), updateResp.GetSessionToken(), updateResp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantIntentFactor)
verifyCurrentSession(t, createResp.GetSessionId(), updateResp.GetSessionToken(), updateResp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantIntentFactor)
}
func TestServer_CreateSession_successfulIntentUnknownUserID(t *testing.T) {
@ -304,7 +338,7 @@ func TestServer_CreateSession_successfulIntentUnknownUserID(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil, nil)
idpUserID := "id"
intentID, token, _, _ := Tester.CreateSuccessfulOAuthIntent(t, idpID, "", idpUserID)
@ -331,7 +365,7 @@ func TestServer_CreateSession_successfulIntentUnknownUserID(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), updateResp.GetSessionToken(), updateResp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantIntentFactor)
verifyCurrentSession(t, createResp.GetSessionId(), updateResp.GetSessionToken(), updateResp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantIntentFactor)
}
func TestServer_CreateSession_startedIntentFalseToken(t *testing.T) {
@ -347,7 +381,7 @@ func TestServer_CreateSession_startedIntentFalseToken(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), createResp.GetSessionToken(), createResp.GetDetails().GetSequence(), time.Minute, nil, nil)
intentID := Tester.CreateIntent(t, idpID)
_, err = Client.SetSession(CTX, &session.SetSessionRequest{
@ -399,7 +433,7 @@ func TestServer_SetSession_flow(t *testing.T) {
createResp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{})
require.NoError(t, err)
sessionToken := createResp.GetSessionToken()
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, createResp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, createResp.GetDetails().GetSequence(), time.Minute, nil, nil)
t.Run("check user", func(t *testing.T) {
resp, err := Client.SetSession(CTX, &session.SetSessionRequest{
@ -415,7 +449,7 @@ func TestServer_SetSession_flow(t *testing.T) {
})
require.NoError(t, err)
sessionToken = resp.GetSessionToken()
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor)
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor)
})
t.Run("check webauthn, user verified (passkey)", func(t *testing.T) {
@ -430,7 +464,7 @@ func TestServer_SetSession_flow(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil, nil)
sessionToken = resp.GetSessionToken()
assertionData, err := Tester.WebAuthN.CreateAssertionResponse(resp.GetChallenges().GetWebAuthN().GetPublicKeyCredentialRequestOptions(), true)
@ -447,7 +481,7 @@ func TestServer_SetSession_flow(t *testing.T) {
})
require.NoError(t, err)
sessionToken = resp.GetSessionToken()
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantWebAuthNFactorUserVerified)
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantWebAuthNFactorUserVerified)
})
userAuthCtx := Tester.WithAuthorizationToken(CTX, sessionToken)
@ -474,7 +508,7 @@ func TestServer_SetSession_flow(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil, nil)
sessionToken = resp.GetSessionToken()
assertionData, err := Tester.WebAuthN.CreateAssertionResponse(resp.GetChallenges().GetWebAuthN().GetPublicKeyCredentialRequestOptions(), false)
@ -491,7 +525,7 @@ func TestServer_SetSession_flow(t *testing.T) {
})
require.NoError(t, err)
sessionToken = resp.GetSessionToken()
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantWebAuthNFactor)
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantWebAuthNFactor)
})
}
})
@ -510,7 +544,7 @@ func TestServer_SetSession_flow(t *testing.T) {
})
require.NoError(t, err)
sessionToken = resp.GetSessionToken()
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantWebAuthNFactor, wantTOTPFactor)
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantWebAuthNFactor, wantTOTPFactor)
})
t.Run("check OTP SMS", func(t *testing.T) {
@ -522,7 +556,7 @@ func TestServer_SetSession_flow(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil, nil)
sessionToken = resp.GetSessionToken()
otp := resp.GetChallenges().GetOtpSms()
@ -539,7 +573,7 @@ func TestServer_SetSession_flow(t *testing.T) {
})
require.NoError(t, err)
sessionToken = resp.GetSessionToken()
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantWebAuthNFactor, wantOTPSMSFactor)
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantWebAuthNFactor, wantOTPSMSFactor)
})
t.Run("check OTP Email", func(t *testing.T) {
@ -553,7 +587,7 @@ func TestServer_SetSession_flow(t *testing.T) {
},
})
require.NoError(t, err)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil)
verifyCurrentSession(t, createResp.GetSessionId(), resp.GetSessionToken(), resp.GetDetails().GetSequence(), time.Minute, nil, nil)
sessionToken = resp.GetSessionToken()
otp := resp.GetChallenges().GetOtpEmail()
@ -570,7 +604,7 @@ func TestServer_SetSession_flow(t *testing.T) {
})
require.NoError(t, err)
sessionToken = resp.GetSessionToken()
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, wantUserFactor, wantWebAuthNFactor, wantOTPEmailFactor)
verifyCurrentSession(t, createResp.GetSessionId(), sessionToken, resp.GetDetails().GetSequence(), time.Minute, nil, nil, wantUserFactor, wantWebAuthNFactor, wantOTPEmailFactor)
})
}

View File

@ -2,15 +2,19 @@ package session
import (
"context"
"net"
"net/http"
"testing"
"time"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/domain"
caos_errs "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query"
@ -23,7 +27,7 @@ func Test_sessionsToPb(t *testing.T) {
past := now.Add(-time.Hour)
sessions := []*query.Session{
{ // no factor
{ // no factor, with user agent
ID: "999",
CreationDate: now,
ChangeDate: now,
@ -32,6 +36,12 @@ func Test_sessionsToPb(t *testing.T) {
ResourceOwner: "me",
Creator: "he",
Metadata: map[string][]byte{"hello": []byte("world")},
UserAgent: domain.UserAgent{
FingerprintID: gu.Ptr("fingerprintID"),
Description: gu.Ptr("description"),
IP: net.IPv4(1, 2, 3, 4),
Header: http.Header{"foo": []string{"foo", "bar"}},
},
},
{ // user factor
ID: "999",
@ -114,13 +124,21 @@ func Test_sessionsToPb(t *testing.T) {
}
want := []*session.Session{
{ // no factor
{ // no factor, with user agent
Id: "999",
CreationDate: timestamppb.New(now),
ChangeDate: timestamppb.New(now),
Sequence: 123,
Factors: nil,
Metadata: map[string][]byte{"hello": []byte("world")},
UserAgent: &session.UserAgent{
FingerprintId: gu.Ptr("fingerprintID"),
Description: gu.Ptr("description"),
Ip: gu.Ptr("1.2.3.4"),
Header: map[string]*session.UserAgent_HeaderValues{
"foo": {Values: []string{"foo", "bar"}},
},
},
},
{ // user factor
Id: "999",
@ -134,6 +152,7 @@ func Test_sessionsToPb(t *testing.T) {
LoginName: "donald",
DisplayName: "donald duck",
OrganisationId: "org1",
OrganizationId: "org1",
},
},
Metadata: map[string][]byte{"hello": []byte("world")},
@ -150,6 +169,7 @@ func Test_sessionsToPb(t *testing.T) {
LoginName: "donald",
DisplayName: "donald duck",
OrganisationId: "org1",
OrganizationId: "org1",
},
Password: &session.PasswordFactor{
VerifiedAt: timestamppb.New(past),
@ -169,6 +189,7 @@ func Test_sessionsToPb(t *testing.T) {
LoginName: "donald",
DisplayName: "donald duck",
OrganisationId: "org1",
OrganizationId: "org1",
},
WebAuthN: &session.WebAuthNFactor{
VerifiedAt: timestamppb.New(past),
@ -189,6 +210,7 @@ func Test_sessionsToPb(t *testing.T) {
LoginName: "donald",
DisplayName: "donald duck",
OrganisationId: "org1",
OrganizationId: "org1",
},
Totp: &session.TOTPFactor{
VerifiedAt: timestamppb.New(past),
@ -208,6 +230,71 @@ func Test_sessionsToPb(t *testing.T) {
}
}
func Test_userAgentToPb(t *testing.T) {
type args struct {
ua domain.UserAgent
}
tests := []struct {
name string
args args
want *session.UserAgent
}{
{
name: "empty",
args: args{domain.UserAgent{}},
},
{
name: "fingerprint id and description",
args: args{domain.UserAgent{
FingerprintID: gu.Ptr("fingerPrintID"),
Description: gu.Ptr("description"),
}},
want: &session.UserAgent{
FingerprintId: gu.Ptr("fingerPrintID"),
Description: gu.Ptr("description"),
},
},
{
name: "with ip",
args: args{domain.UserAgent{
FingerprintID: gu.Ptr("fingerPrintID"),
Description: gu.Ptr("description"),
IP: net.IPv4(1, 2, 3, 4),
}},
want: &session.UserAgent{
FingerprintId: gu.Ptr("fingerPrintID"),
Description: gu.Ptr("description"),
Ip: gu.Ptr("1.2.3.4"),
},
},
{
name: "with header",
args: args{domain.UserAgent{
FingerprintID: gu.Ptr("fingerPrintID"),
Description: gu.Ptr("description"),
Header: http.Header{
"foo": []string{"foo", "bar"},
"hello": []string{"world"},
},
}},
want: &session.UserAgent{
FingerprintId: gu.Ptr("fingerPrintID"),
Description: gu.Ptr("description"),
Header: map[string]*session.UserAgent_HeaderValues{
"foo": {Values: []string{"foo", "bar"}},
"hello": {Values: []string{"world"}},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := userAgentToPb(tt.args.ua)
assert.Equal(t, tt.want, got)
})
}
}
func mustNewTextQuery(t testing.TB, column query.Column, value string, compare query.TextComparison) query.SearchQuery {
q, err := query.NewTextQuery(column, value, compare)
require.NoError(t, err)
@ -510,3 +597,73 @@ func Test_userVerificationRequirementToDomain(t *testing.T) {
})
}
}
func Test_userAgentToCommand(t *testing.T) {
type args struct {
userAgent *session.UserAgent
}
tests := []struct {
name string
args args
want *domain.UserAgent
}{
{
name: "nil",
args: args{nil},
want: nil,
},
{
name: "all fields",
args: args{&session.UserAgent{
FingerprintId: gu.Ptr("fp1"),
Ip: gu.Ptr("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: map[string]*session.UserAgent_HeaderValues{
"hello": {
Values: []string{"foo", "bar"},
},
},
}},
want: &domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{
"hello": []string{"foo", "bar"},
},
},
},
{
name: "invalid ip",
args: args{&session.UserAgent{
FingerprintId: gu.Ptr("fp1"),
Ip: gu.Ptr("oops"),
Description: gu.Ptr("firefox"),
Header: map[string]*session.UserAgent_HeaderValues{
"hello": {
Values: []string{"foo", "bar"},
},
},
}},
want: &domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: nil,
Description: gu.Ptr("firefox"),
Header: http.Header{
"hello": []string{"foo", "bar"},
},
},
},
{
name: "nil fields",
args: args{&session.UserAgent{}},
want: &domain.UserAgent{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := userAgentToCommand(tt.args.userAgent)
assert.Equal(t, tt.want, got)
})
}
}

View File

@ -3,7 +3,7 @@ package system
import (
"strings"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/grpc/authn"

View File

@ -7,8 +7,8 @@ import (
"time"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/api/authz"
http_utils "github.com/zitadel/zitadel/internal/api/http"

View File

@ -6,8 +6,8 @@ import (
"strings"
"time"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"

View File

@ -3,7 +3,7 @@ package oidc
import (
"time"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/command"
)

View File

@ -11,8 +11,8 @@ import (
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
http_utils "github.com/zitadel/zitadel/internal/api/http"
oidc_api "github.com/zitadel/zitadel/internal/api/oidc"
@ -103,7 +103,7 @@ func TestOPStorage_CreateAccessToken_implicit(t *testing.T) {
assert.Equal(t, "state", values.Get("state"))
// check id_token / claims
provider, err := Tester.CreateRelyingParty(clientID, redirectURIImplicit)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURIImplicit)
require.NoError(t, err)
claims, err := rp.VerifyTokens[*oidc.IDTokenClaims](context.Background(), accessToken, idToken, provider.IDTokenVerifier())
require.NoError(t, err)
@ -147,7 +147,7 @@ func TestOPStorage_CreateAccessAndRefreshTokens_code(t *testing.T) {
func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -177,13 +177,13 @@ func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) {
assertIDTokenClaims(t, newTokens.IDTokenClaims, armPasskey, startTime, changeTime)
// refresh with an old refresh_token must fail
_, err = rp.RefreshAccessToken(provider, tokens.RefreshToken, "", "")
_, err = rp.RefreshTokens[*oidc.IDTokenClaims](CTX, provider, tokens.RefreshToken, "", "")
require.Error(t, err)
}
func TestOPStorage_RevokeToken_access_token(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -206,11 +206,11 @@ func TestOPStorage_RevokeToken_access_token(t *testing.T) {
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// revoke access token
err = rp.RevokeToken(provider, tokens.AccessToken, "access_token")
err = rp.RevokeToken(CTX, provider, tokens.AccessToken, "access_token")
require.NoError(t, err)
// userinfo must fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.Error(t, err)
// refresh grant must still work
@ -218,15 +218,15 @@ func TestOPStorage_RevokeToken_access_token(t *testing.T) {
require.NoError(t, err)
// revocation with the same access token must not fail (with or without hint)
err = rp.RevokeToken(provider, tokens.AccessToken, "access_token")
err = rp.RevokeToken(CTX, provider, tokens.AccessToken, "access_token")
require.NoError(t, err)
err = rp.RevokeToken(provider, tokens.AccessToken, "")
err = rp.RevokeToken(CTX, provider, tokens.AccessToken, "")
require.NoError(t, err)
}
func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -249,11 +249,11 @@ func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// revoke access token
err = rp.RevokeToken(provider, tokens.AccessToken, "refresh_token")
err = rp.RevokeToken(CTX, provider, tokens.AccessToken, "refresh_token")
require.NoError(t, err)
// userinfo must fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.Error(t, err)
// refresh grant must still work
@ -263,7 +263,7 @@ func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T
func TestOPStorage_RevokeToken_refresh_token(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -286,11 +286,11 @@ func TestOPStorage_RevokeToken_refresh_token(t *testing.T) {
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// revoke refresh token -> invalidates also access token
err = rp.RevokeToken(provider, tokens.RefreshToken, "refresh_token")
err = rp.RevokeToken(CTX, provider, tokens.RefreshToken, "refresh_token")
require.NoError(t, err)
// userinfo must fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.Error(t, err)
// refresh must fail
@ -298,15 +298,15 @@ func TestOPStorage_RevokeToken_refresh_token(t *testing.T) {
require.Error(t, err)
// revocation with the same refresh token must not fail (with or without hint)
err = rp.RevokeToken(provider, tokens.RefreshToken, "refresh_token")
err = rp.RevokeToken(CTX, provider, tokens.RefreshToken, "refresh_token")
require.NoError(t, err)
err = rp.RevokeToken(provider, tokens.RefreshToken, "")
err = rp.RevokeToken(CTX, provider, tokens.RefreshToken, "")
require.NoError(t, err)
}
func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -329,11 +329,11 @@ func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing.
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// revoke refresh token even with a wrong hint
err = rp.RevokeToken(provider, tokens.RefreshToken, "access_token")
err = rp.RevokeToken(CTX, provider, tokens.RefreshToken, "access_token")
require.NoError(t, err)
// userinfo must fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.Error(t, err)
// refresh must fail
@ -365,15 +365,15 @@ func TestOPStorage_RevokeToken_invalid_client(t *testing.T) {
// simulate second client (not part of the audience) trying to revoke the token
otherClientID := createClient(t)
provider, err := Tester.CreateRelyingParty(otherClientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, otherClientID, redirectURI)
require.NoError(t, err)
err = rp.RevokeToken(provider, tokens.AccessToken, "")
err = rp.RevokeToken(CTX, provider, tokens.AccessToken, "")
require.Error(t, err)
}
func TestOPStorage_TerminateSession(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -396,21 +396,21 @@ func TestOPStorage_TerminateSession(t *testing.T) {
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// userinfo must not fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.NoError(t, err)
postLogoutRedirect, err := rp.EndSession(provider, tokens.IDToken, logoutRedirectURI, "state")
postLogoutRedirect, err := rp.EndSession(CTX, provider, tokens.IDToken, logoutRedirectURI, "state")
require.NoError(t, err)
assert.Equal(t, logoutRedirectURI+"?state=state", postLogoutRedirect.String())
// userinfo must fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.Error(t, err)
}
func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -433,28 +433,28 @@ func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) {
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// userinfo must not fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.NoError(t, err)
postLogoutRedirect, err := rp.EndSession(provider, tokens.IDToken, logoutRedirectURI, "state")
postLogoutRedirect, err := rp.EndSession(CTX, provider, tokens.IDToken, logoutRedirectURI, "state")
require.NoError(t, err)
assert.Equal(t, logoutRedirectURI+"?state=state", postLogoutRedirect.String())
// userinfo must fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.Error(t, err)
refreshedTokens, err := refreshTokens(t, clientID, tokens.RefreshToken)
require.NoError(t, err)
// userinfo must not fail
_, err = rp.Userinfo(refreshedTokens.AccessToken, refreshedTokens.TokenType, refreshedTokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, refreshedTokens.AccessToken, refreshedTokens.TokenType, refreshedTokens.IDTokenClaims.Subject, provider)
require.NoError(t, err)
}
func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -476,12 +476,12 @@ func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) {
assertTokens(t, tokens, false)
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
postLogoutRedirect, err := rp.EndSession(provider, "", logoutRedirectURI, "state")
postLogoutRedirect, err := rp.EndSession(CTX, provider, "", logoutRedirectURI, "state")
require.NoError(t, err)
assert.Equal(t, http_utils.BuildOrigin(Tester.Host(), Tester.Config.ExternalSecure)+Tester.Config.OIDC.DefaultLogoutURLV2+logoutRedirectURI+"?state=state", postLogoutRedirect.String())
// userinfo must not fail until login UI terminated session
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.NoError(t, err)
// simulate termination by login UI
@ -492,12 +492,12 @@ func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) {
require.NoError(t, err)
// userinfo must fail
_, err = rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.Error(t, err)
}
func exchangeTokens(t testing.TB, clientID, code string) (*oidc.Tokens[*oidc.IDTokenClaims], error) {
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
codeVerifier := "codeVerifier"
@ -505,23 +505,10 @@ func exchangeTokens(t testing.TB, clientID, code string) (*oidc.Tokens[*oidc.IDT
}
func refreshTokens(t testing.TB, clientID, refreshToken string) (*oidc.Tokens[*oidc.IDTokenClaims], error) {
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
tokens, err := rp.RefreshAccessToken(provider, refreshToken, "", "")
if err != nil {
return nil, err
}
idToken, _ := tokens.Extra("id_token").(string)
claims, err := rp.VerifyTokens[*oidc.IDTokenClaims](context.Background(), tokens.AccessToken, idToken, provider.IDTokenVerifier())
if err != nil {
return nil, err
}
return &oidc.Tokens[*oidc.IDTokenClaims]{
Token: tokens,
IDToken: idToken,
IDTokenClaims: claims,
}, nil
return rp.RefreshTokens[*oidc.IDTokenClaims](CTX, provider, refreshToken, "", "")
}
func assertCodeResponse(t *testing.T, callback string) string {

View File

@ -9,10 +9,10 @@ import (
"time"
"github.com/dop251/goja"
"github.com/go-jose/go-jose/v3"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/actions"
"github.com/zitadel/zitadel/internal/actions/object"
@ -564,7 +564,7 @@ func (o *OPStorage) userinfoFlows(ctx context.Context, user *query.User, userGra
apiFields,
action.Script,
action.Name,
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx))...,
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
)
cancel()
if err != nil {
@ -745,7 +745,7 @@ func (o *OPStorage) privateClaimsFlows(ctx context.Context, userID string, userG
apiFields,
action.Script,
action.Name,
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx))...,
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
)
cancel()
if err != nil {

View File

@ -4,8 +4,8 @@ import (
"strings"
"time"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"

View File

@ -3,8 +3,8 @@ package oidc
import (
"time"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
)
type clientCredentialsRequest struct {

View File

@ -9,9 +9,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/client/rs"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/client/rs"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/pkg/grpc/authn"
"github.com/zitadel/zitadel/pkg/grpc/management"
@ -41,9 +41,9 @@ func TestOPStorage_SetUserinfoFromToken(t *testing.T) {
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// test actual userinfo
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
userinfo, err := rp.Userinfo(tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
require.NoError(t, err)
assertUserinfo(t, userinfo)
}
@ -62,7 +62,7 @@ func TestOPStorage_SetIntrospectionFromToken(t *testing.T) {
ExpirationDate: nil,
})
require.NoError(t, err)
resourceServer, err := Tester.CreateResourceServer(keyResp.GetKeyDetails())
resourceServer, err := Tester.CreateResourceServer(CTX, keyResp.GetKeyDetails())
require.NoError(t, err)
scope := []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeOfflineAccess}
@ -87,7 +87,7 @@ func TestOPStorage_SetIntrospectionFromToken(t *testing.T) {
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
// test actual introspection
introspection, err := rs.Introspect(context.Background(), resourceServer, tokens.AccessToken)
introspection, err := rs.Introspect[*oidc.IntrospectionResponse](context.Background(), resourceServer, tokens.AccessToken)
require.NoError(t, err)
assertIntrospection(t, introspection,
Tester.OIDCIssuer(), app.GetClientId(),

View File

@ -5,8 +5,8 @@ import (
"time"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/api/ui/login"
"github.com/zitadel/zitadel/internal/domain"

View File

@ -3,8 +3,8 @@ package oidc
import (
"context"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"

View File

@ -5,9 +5,9 @@ import (
"fmt"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/op"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"

View File

@ -11,8 +11,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"google.golang.org/grpc/metadata"
"github.com/zitadel/zitadel/internal/domain"
@ -216,7 +216,7 @@ func Test_ZITADEL_API_inactive_access_token(t *testing.T) {
func Test_ZITADEL_API_terminated_session(t *testing.T) {
clientID := createClient(t)
provider, err := Tester.CreateRelyingParty(clientID, redirectURI)
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
require.NoError(t, err)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerfiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
@ -245,7 +245,7 @@ func Test_ZITADEL_API_terminated_session(t *testing.T) {
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId())
// refresh token
postLogoutRedirect, err := rp.EndSession(provider, tokens.IDToken, logoutRedirectURI, "state")
postLogoutRedirect, err := rp.EndSession(CTX, provider, tokens.IDToken, logoutRedirectURI, "state")
require.NoError(t, err)
assert.Equal(t, logoutRedirectURI+"?state=state", postLogoutRedirect.String())
@ -271,13 +271,13 @@ func createImplicitClient(t testing.TB) string {
}
func createAuthRequest(t testing.TB, clientID, redirectURI string, scope ...string) string {
redURL, err := Tester.CreateOIDCAuthRequest(clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...)
redURL, err := Tester.CreateOIDCAuthRequest(CTX, clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...)
require.NoError(t, err)
return redURL
}
func createAuthRequestImplicit(t testing.TB, clientID, redirectURI string, scope ...string) string {
redURL, err := Tester.CreateOIDCAuthRequestImplicit(clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...)
redURL, err := Tester.CreateOIDCAuthRequestImplicit(CTX, clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...)
require.NoError(t, err)
return redURL
}

View File

@ -7,8 +7,8 @@ import (
"time"
"github.com/rakyll/statik/fs"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/assets"

View File

@ -5,9 +5,9 @@ import (
"fmt"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/zitadel/logging"
"github.com/zitadel/saml/pkg/provider/key"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"

View File

@ -15,7 +15,7 @@ import (
"github.com/gorilla/mux"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/op"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/cmd/build"
"github.com/zitadel/zitadel/internal/api/authz"

View File

@ -7,7 +7,7 @@ import (
"github.com/dop251/goja"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/actions"
@ -133,7 +133,7 @@ func (l *Login) runPostExternalAuthenticationActions(
apiFields,
a.Script,
a.Name,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
)
cancel()
if err != nil {
@ -206,7 +206,7 @@ func (l *Login) runPostInternalAuthenticationActions(
apiFields,
a.Script,
a.Name,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
)
cancel()
if err != nil {
@ -307,7 +307,7 @@ func (l *Login) runPreCreationActions(
apiFields,
a.Script,
a.Name,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
)
cancel()
if err != nil {
@ -365,7 +365,7 @@ func (l *Login) runPostCreationActions(
apiFields,
a.Script,
a.Name,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
)
cancel()
if err != nil {

View File

@ -7,8 +7,8 @@ import (
"github.com/crewjam/saml/samlsp"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -8,7 +8,7 @@ import (
"strings"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
http_util "github.com/zitadel/zitadel/internal/api/http"

View File

@ -7,10 +7,10 @@ import (
"strings"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/api/authz"
http_util "github.com/zitadel/zitadel/internal/api/http"
@ -274,7 +274,7 @@ func (repo *TokenVerifierRepo) getTokenIDAndSubject(ctx context.Context, accessT
return splitToken[0], splitToken[1], true
}
func (repo *TokenVerifierRepo) jwtTokenVerifier(ctx context.Context) op.AccessTokenVerifier {
func (repo *TokenVerifierRepo) jwtTokenVerifier(ctx context.Context) *op.AccessTokenVerifier {
keySet := &openIDKeySet{repo.Query}
issuer := http_util.BuildOrigin(authz.GetInstance(ctx).RequestedHost(), repo.ExternalSecure)
return op.NewAccessTokenVerifier(issuer, keySet)

View File

@ -2,6 +2,8 @@ package command
import (
"context"
"net"
"net/http"
"testing"
"time"
@ -354,7 +356,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(mockCtx,
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
),
),
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
@ -397,7 +407,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(mockCtx,
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
),
),
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
@ -440,8 +458,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate),
),
session.NewAddedEvent(mockCtx,
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
"userID", testNow),
@ -517,8 +542,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate),
),
session.NewAddedEvent(mockCtx,
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
"userID", testNow),

View File

@ -9,7 +9,7 @@ import (
"github.com/crewjam/saml"
"github.com/crewjam/saml/samlsp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"

View File

@ -9,7 +9,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -7,7 +7,7 @@ import (
"time"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"golang.org/x/oauth2"
"github.com/zitadel/zitadel/internal/crypto"

View File

@ -8,7 +8,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"

View File

@ -2,6 +2,8 @@ package command
import (
"context"
"net"
"net/http"
"testing"
"time"
@ -163,7 +165,15 @@ func TestCommands_AddOIDCSessionAccessToken(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
),
),
eventFromEventPusher(
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
@ -356,7 +366,15 @@ func TestCommands_AddOIDCSessionRefreshAndAccessToken(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
),
),
eventFromEventPusher(
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,

View File

@ -8,7 +8,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"

View File

@ -7,7 +7,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"

View File

@ -166,8 +166,8 @@ func (s *SessionCommands) Exec(ctx context.Context) error {
return nil
}
func (s *SessionCommands) Start(ctx context.Context) {
s.eventCommands = append(s.eventCommands, session.NewAddedEvent(ctx, s.sessionWriteModel.aggregate))
func (s *SessionCommands) Start(ctx context.Context, userAgent *domain.UserAgent) {
s.eventCommands = append(s.eventCommands, session.NewAddedEvent(ctx, s.sessionWriteModel.aggregate, userAgent))
}
func (s *SessionCommands) UserChecked(ctx context.Context, userID string, checkedAt time.Time) error {
@ -280,7 +280,7 @@ func (s *SessionCommands) commands(ctx context.Context) (string, []eventstore.Co
return token, s.eventCommands, nil
}
func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, metadata map[string][]byte) (set *SessionChanged, err error) {
func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, metadata map[string][]byte, userAgent *domain.UserAgent) (set *SessionChanged, err error) {
sessionID, err := c.idGenerator.Next()
if err != nil {
return nil, err
@ -291,7 +291,7 @@ func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, met
return nil, err
}
cmd := c.NewSessionCommands(cmds, sessionWriteModel)
cmd.Start(ctx)
cmd.Start(ctx, userAgent)
return c.updateSession(ctx, cmd, metadata)
}

View File

@ -3,10 +3,13 @@ package command
import (
"context"
"io"
"net"
"net/http"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/muhlemmer/gu"
"github.com/pquerna/otp/totp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -145,9 +148,10 @@ func TestCommands_CreateSession(t *testing.T) {
tokenCreator func(sessionID string) (string, string, error)
}
type args struct {
ctx context.Context
checks []SessionCommand
metadata map[string][]byte
ctx context.Context
checks []SessionCommand
metadata map[string][]byte
userAgent *domain.UserAgent
}
type res struct {
want *SessionChanged
@ -200,11 +204,25 @@ func TestCommands_CreateSession(t *testing.T) {
},
args{
ctx: authz.NewMockContext("", "org1", ""),
userAgent: &domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
},
[]expect{
expectFilter(),
expectPush(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
),
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
"tokenID",
),
@ -227,7 +245,7 @@ func TestCommands_CreateSession(t *testing.T) {
idGenerator: tt.fields.idGenerator,
sessionTokenCreator: tt.fields.tokenCreator,
}
got, err := c.CreateSession(tt.args.ctx, tt.args.checks, tt.args.metadata)
got, err := c.CreateSession(tt.args.ctx, tt.args.checks, tt.args.metadata, tt.args.userAgent)
require.ErrorIs(t, err, tt.res.err)
assert.Equal(t, tt.res.want, got)
})
@ -276,7 +294,15 @@ func TestCommands_UpdateSession(t *testing.T) {
eventstore: eventstoreExpect(t,
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
"tokenID")),
@ -301,7 +327,15 @@ func TestCommands_UpdateSession(t *testing.T) {
eventstore: eventstoreExpect(t,
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
"tokenID")),
@ -866,7 +900,15 @@ func TestCommands_TerminateSession(t *testing.T) {
eventstore: eventstoreExpect(t,
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
"tokenID")),
@ -891,7 +933,15 @@ func TestCommands_TerminateSession(t *testing.T) {
eventstore: eventstoreExpect(t,
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
"tokenID")),
@ -920,7 +970,15 @@ func TestCommands_TerminateSession(t *testing.T) {
eventstore: eventstoreExpect(t,
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
"tokenID"),
@ -950,7 +1008,15 @@ func TestCommands_TerminateSession(t *testing.T) {
eventstore: eventstoreExpect(t,
expectFilter(
eventFromEventPusher(
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
session.NewAddedEvent(context.Background(),
&session.NewAggregate("sessionID", "org1").Aggregate,
&domain.UserAgent{
FingerprintID: gu.Ptr("fp1"),
IP: net.ParseIP("1.2.3.4"),
Description: gu.Ptr("firefox"),
Header: http.Header{"foo": []string{"bar"}},
},
)),
eventFromEventPusher(
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
"tokenID"),

View File

@ -8,7 +8,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"

View File

@ -147,7 +147,7 @@ func (c *HasherConfig) buildHasher() (hasher passwap.Hasher, prefixes []string,
func (c *HasherConfig) decodeParams(dst any) error {
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
ErrorUnused: true,
ErrorUnused: false,
ErrorUnset: true,
Result: dst,
})

View File

@ -379,7 +379,10 @@ func TestHasherConfig_decodeParams(t *testing.T) {
"b": 2,
"c": 3,
},
wantErr: true,
want: dst{
A: 1,
B: 2,
},
},
{
name: "unset",

View File

@ -0,0 +1,17 @@
package domain
import (
"net"
httplib "net/http"
)
type UserAgent struct {
FingerprintID *string `json:"fingerprint_id,omitempty"`
IP net.IP `json:"ip,omitempty"`
Description *string `json:"description,omitempty"`
Header httplib.Header `json:"header,omitempty"`
}
func (ua UserAgent) IsEmpty() bool {
return ua.FingerprintID == nil && len(ua.IP) == 0 && ua.Description == nil && ua.Header == nil
}

View File

@ -5,9 +5,9 @@ import (
"encoding/pem"
"time"
"github.com/zitadel/oidc/v2/pkg/crypto"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
"gopkg.in/square/go-jose.v2"
"github.com/go-jose/go-jose/v3"
"github.com/zitadel/oidc/v3/pkg/crypto"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/idp/providers/oidc"

View File

@ -4,7 +4,7 @@ import (
"context"
"encoding/json"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/idp/providers/oidc"

View File

@ -9,7 +9,7 @@ import (
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -3,7 +3,7 @@ package azuread
import (
"fmt"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -6,8 +6,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/idp/providers/oauth"

View File

@ -3,8 +3,8 @@ package azuread
import (
"net/http"
httphelper "github.com/zitadel/oidc/v2/pkg/http"
"github.com/zitadel/oidc/v2/pkg/oidc"
httphelper "github.com/zitadel/oidc/v3/pkg/http"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp/providers/oauth"
)

View File

@ -10,7 +10,7 @@ import (
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -10,7 +10,7 @@ import (
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -1,7 +1,7 @@
package gitlab
import (
openid "github.com/zitadel/oidc/v2/pkg/oidc"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/idp/providers/oidc"

View File

@ -9,8 +9,8 @@ import (
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -1,7 +1,7 @@
package google
import (
openid "github.com/zitadel/oidc/v2/pkg/oidc"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/idp/providers/oidc"

View File

@ -9,8 +9,8 @@ import (
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
openid "github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
openid "github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -8,8 +8,8 @@ import (
"time"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/domain"

View File

@ -7,14 +7,14 @@ import (
"testing"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/golang/mock/gomock"
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"

View File

@ -3,8 +3,8 @@ package oauth
import (
"context"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"github.com/zitadel/zitadel/internal/idp"

View File

@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"golang.org/x/oauth2"
"github.com/zitadel/zitadel/internal/idp"

View File

@ -5,9 +5,9 @@ import (
"errors"
"net/http"
"github.com/zitadel/oidc/v2/pkg/client/rp"
httphelper "github.com/zitadel/oidc/v2/pkg/http"
"github.com/zitadel/oidc/v2/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"
"github.com/zitadel/zitadel/internal/idp"
)

View File

@ -9,7 +9,7 @@ import (
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"

View File

@ -3,8 +3,8 @@ package oidc
import (
"context"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp"
)
@ -100,7 +100,7 @@ func New(name, issuer, clientID, clientSecret, redirectURI string, scopes []stri
for _, option := range options {
option(provider)
}
provider.RelyingParty, err = rp.NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI, setDefaultScope(scopes), provider.options...)
provider.RelyingParty, err = rp.NewRelyingPartyOIDC(context.TODO(), issuer, clientID, clientSecret, redirectURI, setDefaultScope(scopes), provider.options...)
if err != nil {
return nil, err
}

View File

@ -7,8 +7,8 @@ import (
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/internal/idp"
)

View File

@ -4,8 +4,8 @@ import (
"context"
"errors"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/domain"
@ -38,7 +38,7 @@ func (s *Session) FetchUser(ctx context.Context) (user idp.User, err error) {
return nil, err
}
}
info, err := rp.Userinfo(
info, err := rp.Userinfo[*oidc.UserInfo](ctx,
s.Tokens.AccessToken,
s.Tokens.TokenType,
s.Tokens.IDTokenClaims.GetSubject(),

View File

@ -7,14 +7,14 @@ import (
"testing"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"

View File

@ -9,7 +9,7 @@ import (
crewjam_saml "github.com/crewjam/saml"
"github.com/stretchr/testify/require"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"
"google.golang.org/grpc"

View File

@ -19,8 +19,8 @@ import (
"github.com/spf13/viper"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/client"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client"
"github.com/zitadel/oidc/v3/pkg/oidc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"

View File

@ -8,10 +8,10 @@ import (
"strings"
"time"
"github.com/zitadel/oidc/v2/pkg/client"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/client/rs"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/client"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/client/rs"
"github.com/zitadel/oidc/v3/pkg/oidc"
http_util "github.com/zitadel/zitadel/internal/api/http"
oidc_internal "github.com/zitadel/zitadel/internal/api/oidc"
@ -83,8 +83,8 @@ func (s *Tester) CreateAPIClient(ctx context.Context, projectID string) (*manage
})
}
func (s *Tester) CreateOIDCAuthRequest(clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) {
provider, err := s.CreateRelyingParty(clientID, redirectURI, scope...)
func (s *Tester) CreateOIDCAuthRequest(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) {
provider, err := s.CreateRelyingParty(ctx, clientID, redirectURI, scope...)
if err != nil {
return "", err
}
@ -110,8 +110,8 @@ func (s *Tester) CreateOIDCAuthRequest(clientID, loginClient, redirectURI string
return strings.TrimPrefix(loc.String(), prefixWithHost), nil
}
func (s *Tester) CreateOIDCAuthRequestImplicit(clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) {
provider, err := s.CreateRelyingParty(clientID, redirectURI, scope...)
func (s *Tester) CreateOIDCAuthRequestImplicit(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) {
provider, err := s.CreateRelyingParty(ctx, clientID, redirectURI, scope...)
if err != nil {
return "", err
}
@ -146,12 +146,12 @@ func (s *Tester) OIDCIssuer() string {
return http_util.BuildHTTP(s.Config.ExternalDomain, s.Config.Port, s.Config.ExternalSecure)
}
func (s *Tester) CreateRelyingParty(clientID, redirectURI string, scope ...string) (rp.RelyingParty, error) {
func (s *Tester) CreateRelyingParty(ctx context.Context, clientID, redirectURI string, scope ...string) (rp.RelyingParty, error) {
if len(scope) == 0 {
scope = []string{oidc.ScopeOpenID}
}
loginClient := &http.Client{Transport: &loginRoundTripper{http.DefaultTransport}}
return rp.NewRelyingPartyOIDC(s.OIDCIssuer(), clientID, "", redirectURI, scope, rp.WithHTTPClient(loginClient))
return rp.NewRelyingPartyOIDC(ctx, s.OIDCIssuer(), clientID, "", redirectURI, scope, rp.WithHTTPClient(loginClient))
}
type loginRoundTripper struct {
@ -163,12 +163,12 @@ func (c *loginRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
return c.RoundTripper.RoundTrip(req)
}
func (s *Tester) CreateResourceServer(keyFileData []byte) (rs.ResourceServer, error) {
func (s *Tester) CreateResourceServer(ctx context.Context, keyFileData []byte) (rs.ResourceServer, error) {
keyFile, err := client.ConfigFromKeyFileData(keyFileData)
if err != nil {
return nil, err
}
return rs.NewResourceServerJWTProfile(s.OIDCIssuer(), keyFile.ClientID, keyFile.KeyID, []byte(keyFile.Key))
return rs.NewResourceServerJWTProfile(ctx, s.OIDCIssuer(), keyFile.ClientID, keyFile.KeyID, []byte(keyFile.Key))
}
func GetRequest(url string, headers map[string]string) (*http.Request, error) {

View File

@ -17,8 +17,8 @@ var {{.ServiceName}}_AuthMethods = authz.MethodMapping {
}
{{ range $m := .AuthContext}}
func (r *{{ $m.Name }}) OrganisationFromRequest() *middleware.Organisation {
return &middleware.Organisation{
func (r *{{ $m.Name }}) OrganizationFromRequest() *middleware.Organization {
return &middleware.Organization{
ID: r{{$m.OrgMethod}}.GetOrgId(),
Domain: r{{$m.OrgMethod}}.GetOrgDomain(),
}

View File

@ -54,7 +54,7 @@ func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExp
}
return isErr(err)
}
object, ok, didScan := execScan(&database.DB{DB: client}, builder, scan, errCheck)
object, ok, didScan := execScan(t, &database.DB{DB: client}, builder, scan, errCheck)
if !ok {
t.Error(object)
return false
@ -168,7 +168,7 @@ var (
selectBuilderType = reflect.TypeOf(sq.SelectBuilder{})
)
func execScan(client *database.DB, builder sq.SelectBuilder, scan interface{}, errCheck checkErr) (object interface{}, ok bool, didScan bool) {
func execScan(t testing.TB, client *database.DB, builder sq.SelectBuilder, scan interface{}, errCheck checkErr) (object interface{}, ok bool, didScan bool) {
scanType := reflect.TypeOf(scan)
err := validateScan(scanType)
if err != nil {
@ -177,7 +177,7 @@ func execScan(client *database.DB, builder sq.SelectBuilder, scan interface{}, e
stmt, args, err := builder.ToSql()
if err != nil {
return fmt.Errorf("unexpeted error from sql builder: %w", err), false, false
return fmt.Errorf("unexpected error from sql builder: %w", err), false, false
}
//resultSet represents *sql.Row or *sql.Rows,
@ -199,6 +199,9 @@ func execScan(client *database.DB, builder sq.SelectBuilder, scan interface{}, e
// if scan(*sql.Row)...
} else if scanType.In(0).AssignableTo(rowType) {
err = client.QueryRow(func(r *sql.Row) error {
if r.Err() != nil {
return r.Err()
}
didScan = true
res = reflect.ValueOf(scan).Call([]reflect.Value{reflect.ValueOf(r)})
if err, ok := res[1].Interface().(error); ok {
@ -213,6 +216,9 @@ func execScan(client *database.DB, builder sq.SelectBuilder, scan interface{}, e
if err != nil {
err, ok := errCheck(err)
if !ok {
t.Fatal(err)
}
if didScan {
return res[0].Interface(), ok, didScan
}

View File

@ -14,27 +14,31 @@ import (
)
const (
SessionsProjectionTable = "projections.sessions5"
SessionsProjectionTable = "projections.sessions6"
SessionColumnID = "id"
SessionColumnCreationDate = "creation_date"
SessionColumnChangeDate = "change_date"
SessionColumnSequence = "sequence"
SessionColumnState = "state"
SessionColumnResourceOwner = "resource_owner"
SessionColumnInstanceID = "instance_id"
SessionColumnCreator = "creator"
SessionColumnUserID = "user_id"
SessionColumnUserCheckedAt = "user_checked_at"
SessionColumnPasswordCheckedAt = "password_checked_at"
SessionColumnIntentCheckedAt = "intent_checked_at"
SessionColumnWebAuthNCheckedAt = "webauthn_checked_at"
SessionColumnWebAuthNUserVerified = "webauthn_user_verified"
SessionColumnTOTPCheckedAt = "totp_checked_at"
SessionColumnOTPSMSCheckedAt = "otp_sms_checked_at"
SessionColumnOTPEmailCheckedAt = "otp_email_checked_at"
SessionColumnMetadata = "metadata"
SessionColumnTokenID = "token_id"
SessionColumnID = "id"
SessionColumnCreationDate = "creation_date"
SessionColumnChangeDate = "change_date"
SessionColumnSequence = "sequence"
SessionColumnState = "state"
SessionColumnResourceOwner = "resource_owner"
SessionColumnInstanceID = "instance_id"
SessionColumnCreator = "creator"
SessionColumnUserID = "user_id"
SessionColumnUserCheckedAt = "user_checked_at"
SessionColumnPasswordCheckedAt = "password_checked_at"
SessionColumnIntentCheckedAt = "intent_checked_at"
SessionColumnWebAuthNCheckedAt = "webauthn_checked_at"
SessionColumnWebAuthNUserVerified = "webauthn_user_verified"
SessionColumnTOTPCheckedAt = "totp_checked_at"
SessionColumnOTPSMSCheckedAt = "otp_sms_checked_at"
SessionColumnOTPEmailCheckedAt = "otp_email_checked_at"
SessionColumnMetadata = "metadata"
SessionColumnTokenID = "token_id"
SessionColumnUserAgentFingerprintID = "user_agent_fingerprint_id"
SessionColumnUserAgentIP = "user_agent_ip"
SessionColumnUserAgentDescription = "user_agent_description"
SessionColumnUserAgentHeader = "user_agent_header"
)
type sessionProjection struct{}
@ -69,8 +73,16 @@ func (*sessionProjection) Init() *old_handler.Check {
handler.NewColumn(SessionColumnOTPEmailCheckedAt, handler.ColumnTypeTimestamp, handler.Nullable()),
handler.NewColumn(SessionColumnMetadata, handler.ColumnTypeJSONB, handler.Nullable()),
handler.NewColumn(SessionColumnTokenID, handler.ColumnTypeText, handler.Nullable()),
handler.NewColumn(SessionColumnUserAgentFingerprintID, handler.ColumnTypeText, handler.Nullable()),
handler.NewColumn(SessionColumnUserAgentIP, handler.ColumnTypeText, handler.Nullable()),
handler.NewColumn(SessionColumnUserAgentDescription, handler.ColumnTypeText, handler.Nullable()),
handler.NewColumn(SessionColumnUserAgentHeader, handler.ColumnTypeJSONB, handler.Nullable()),
},
handler.NewPrimaryKey(SessionColumnInstanceID, SessionColumnID),
handler.WithIndex(handler.NewIndex(
SessionColumnUserAgentFingerprintID+"_idx",
[]string{SessionColumnUserAgentFingerprintID},
)),
),
)
}
@ -153,19 +165,35 @@ func (p *sessionProjection) reduceSessionAdded(event eventstore.Event) (*handler
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-Sfrgf", "reduce.wrong.event.type %s", session.AddedType)
}
return handler.NewCreateStatement(
e,
[]handler.Column{
handler.NewCol(SessionColumnID, e.Aggregate().ID),
handler.NewCol(SessionColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SessionColumnCreationDate, e.CreationDate()),
handler.NewCol(SessionColumnChangeDate, e.CreationDate()),
handler.NewCol(SessionColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCol(SessionColumnState, domain.SessionStateActive),
handler.NewCol(SessionColumnSequence, e.Sequence()),
handler.NewCol(SessionColumnCreator, e.User),
},
), nil
cols := make([]handler.Column, 0, 12)
cols = append(cols,
handler.NewCol(SessionColumnID, e.Aggregate().ID),
handler.NewCol(SessionColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SessionColumnCreationDate, e.CreationDate()),
handler.NewCol(SessionColumnChangeDate, e.CreationDate()),
handler.NewCol(SessionColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCol(SessionColumnState, domain.SessionStateActive),
handler.NewCol(SessionColumnSequence, e.Sequence()),
handler.NewCol(SessionColumnCreator, e.User),
)
if e.UserAgent != nil {
cols = append(cols,
handler.NewCol(SessionColumnUserAgentFingerprintID, e.UserAgent.FingerprintID),
handler.NewCol(SessionColumnUserAgentDescription, e.UserAgent.Description),
)
if e.UserAgent.IP != nil {
cols = append(cols,
handler.NewCol(SessionColumnUserAgentIP, e.UserAgent.IP.String()),
)
}
if e.UserAgent.Header != nil {
cols = append(cols,
handler.NewJSONCol(SessionColumnUserAgentHeader, e.UserAgent.Header),
)
}
}
return handler.NewCreateStatement(e, cols), nil
}
func (p *sessionProjection) reduceUserChecked(event eventstore.Event) (*handler.Statement, error) {

View File

@ -4,6 +4,8 @@ import (
"testing"
"time"
"github.com/muhlemmer/gu"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
@ -30,7 +32,15 @@ func TestSessionProjection_reduces(t *testing.T) {
session.AddedType,
session.AggregateType,
[]byte(`{
"domain": "domain"
"domain": "domain",
"user_agent": {
"fingerprint_id": "fp1",
"ip": "1.2.3.4",
"description": "firefox",
"header": {
"foo": ["bar"]
}
}
}`),
), session.AddedEventMapper),
},
@ -41,7 +51,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.sessions5 (id, instance_id, creation_date, change_date, resource_owner, state, sequence, creator) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
expectedStmt: "INSERT INTO projections.sessions6 (id, instance_id, creation_date, change_date, resource_owner, state, sequence, creator, user_agent_fingerprint_id, user_agent_description, user_agent_ip, user_agent_header) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -51,6 +61,10 @@ func TestSessionProjection_reduces(t *testing.T) {
domain.SessionStateActive,
uint64(15),
"editor-user",
gu.Ptr("fp1"),
gu.Ptr("firefox"),
"1.2.3.4",
[]byte(`{"foo":["bar"]}`),
},
},
},
@ -76,7 +90,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET (change_date, sequence, user_id, user_checked_at) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)",
expectedStmt: "UPDATE projections.sessions6 SET (change_date, sequence, user_id, user_checked_at) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@ -108,7 +122,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET (change_date, sequence, password_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.sessions6 SET (change_date, sequence, password_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@ -140,7 +154,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET (change_date, sequence, webauthn_checked_at, webauthn_user_verified) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)",
expectedStmt: "UPDATE projections.sessions6 SET (change_date, sequence, webauthn_checked_at, webauthn_user_verified) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@ -172,7 +186,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET (change_date, sequence, intent_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.sessions6 SET (change_date, sequence, intent_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@ -203,7 +217,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET (change_date, sequence, totp_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.sessions6 SET (change_date, sequence, totp_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@ -234,7 +248,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET (change_date, sequence, token_id) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.sessions6 SET (change_date, sequence, token_id) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@ -267,7 +281,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET (change_date, sequence, metadata) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.sessions6 SET (change_date, sequence, metadata) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@ -298,7 +312,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.sessions5 WHERE (id = $1) AND (instance_id = $2)",
expectedStmt: "DELETE FROM projections.sessions6 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -325,7 +339,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.sessions5 WHERE (instance_id = $1)",
expectedStmt: "DELETE FROM projections.sessions6 WHERE (instance_id = $1)",
expectedArgs: []interface{}{
"agg-id",
},
@ -355,7 +369,7 @@ func TestSessionProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.sessions5 SET password_checked_at = $1 WHERE (user_id = $2) AND (password_checked_at < $3)",
expectedStmt: "UPDATE projections.sessions6 SET password_checked_at = $1 WHERE (user_id = $2) AND (password_checked_at < $3)",
expectedArgs: []interface{}{
nil,
"agg-id",

View File

@ -4,6 +4,8 @@ import (
"context"
"database/sql"
errs "errors"
"net"
"net/http"
"time"
sq "github.com/Masterminds/squirrel"
@ -41,6 +43,7 @@ type Session struct {
OTPSMSFactor SessionOTPFactor
OTPEmailFactor SessionOTPFactor
Metadata map[string][]byte
UserAgent domain.UserAgent
}
type SessionUserFactor struct {
@ -166,6 +169,22 @@ var (
name: projection.SessionColumnTokenID,
table: sessionsTable,
}
SessionColumnUserAgentFingerprintID = Column{
name: projection.SessionColumnUserAgentFingerprintID,
table: sessionsTable,
}
SessionColumnUserAgentIP = Column{
name: projection.SessionColumnUserAgentIP,
table: sessionsTable,
}
SessionColumnUserAgentDescription = Column{
name: projection.SessionColumnUserAgentDescription,
table: sessionsTable,
}
SessionColumnUserAgentHeader = Column{
name: projection.SessionColumnUserAgentHeader,
table: sessionsTable,
}
)
func (q *Queries) SessionByID(ctx context.Context, shouldTriggerBulk bool, id, sessionToken string) (session *Session, err error) {
@ -265,6 +284,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
SessionColumnOTPEmailCheckedAt.identifier(),
SessionColumnMetadata.identifier(),
SessionColumnToken.identifier(),
SessionColumnUserAgentFingerprintID.identifier(),
SessionColumnUserAgentIP.identifier(),
SessionColumnUserAgentDescription.identifier(),
SessionColumnUserAgentHeader.identifier(),
).From(sessionsTable.identifier()).
LeftJoin(join(LoginNameUserIDCol, SessionColumnUserID)).
LeftJoin(join(HumanUserIDCol, SessionColumnUserID)).
@ -287,6 +310,8 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
otpEmailCheckedAt sql.NullTime
metadata database.Map[[]byte]
token sql.NullString
userAgentIP sql.NullString
userAgentHeader database.Map[[]string]
)
err := row.Scan(
@ -311,6 +336,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
&otpEmailCheckedAt,
&metadata,
&token,
&session.UserAgent.FingerprintID,
&userAgentIP,
&session.UserAgent.Description,
&userAgentHeader,
)
if err != nil {
@ -333,7 +362,11 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
session.OTPSMSFactor.OTPCheckedAt = otpSMSCheckedAt.Time
session.OTPEmailFactor.OTPCheckedAt = otpEmailCheckedAt.Time
session.Metadata = metadata
session.UserAgent.Header = http.Header(userAgentHeader)
if userAgentIP.Valid {
session.UserAgent.IP = net.ParseIP(userAgentIP.String)
}
return session, token.String, nil
}
}

View File

@ -6,10 +6,13 @@ import (
"database/sql/driver"
"errors"
"fmt"
"net"
"net/http"
"regexp"
"testing"
sq "github.com/Masterminds/squirrel"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/require"
"github.com/zitadel/zitadel/internal/domain"
@ -17,57 +20,61 @@ import (
)
var (
expectedSessionQuery = regexp.QuoteMeta(`SELECT projections.sessions5.id,` +
` projections.sessions5.creation_date,` +
` projections.sessions5.change_date,` +
` projections.sessions5.sequence,` +
` projections.sessions5.state,` +
` projections.sessions5.resource_owner,` +
` projections.sessions5.creator,` +
` projections.sessions5.user_id,` +
` projections.sessions5.user_checked_at,` +
expectedSessionQuery = regexp.QuoteMeta(`SELECT projections.sessions6.id,` +
` projections.sessions6.creation_date,` +
` projections.sessions6.change_date,` +
` projections.sessions6.sequence,` +
` projections.sessions6.state,` +
` projections.sessions6.resource_owner,` +
` projections.sessions6.creator,` +
` projections.sessions6.user_id,` +
` projections.sessions6.user_checked_at,` +
` projections.login_names2.login_name,` +
` projections.users8_humans.display_name,` +
` projections.users8.resource_owner,` +
` projections.sessions5.password_checked_at,` +
` projections.sessions5.intent_checked_at,` +
` projections.sessions5.webauthn_checked_at,` +
` projections.sessions5.webauthn_user_verified,` +
` projections.sessions5.totp_checked_at,` +
` projections.sessions5.otp_sms_checked_at,` +
` projections.sessions5.otp_email_checked_at,` +
` projections.sessions5.metadata,` +
` projections.sessions5.token_id` +
` FROM projections.sessions5` +
` LEFT JOIN projections.login_names2 ON projections.sessions5.user_id = projections.login_names2.user_id AND projections.sessions5.instance_id = projections.login_names2.instance_id` +
` LEFT JOIN projections.users8_humans ON projections.sessions5.user_id = projections.users8_humans.user_id AND projections.sessions5.instance_id = projections.users8_humans.instance_id` +
` LEFT JOIN projections.users8 ON projections.sessions5.user_id = projections.users8.id AND projections.sessions5.instance_id = projections.users8.instance_id` +
` projections.sessions6.password_checked_at,` +
` projections.sessions6.intent_checked_at,` +
` projections.sessions6.webauthn_checked_at,` +
` projections.sessions6.webauthn_user_verified,` +
` projections.sessions6.totp_checked_at,` +
` projections.sessions6.otp_sms_checked_at,` +
` projections.sessions6.otp_email_checked_at,` +
` projections.sessions6.metadata,` +
` projections.sessions6.token_id,` +
` projections.sessions6.user_agent_fingerprint_id,` +
` projections.sessions6.user_agent_ip,` +
` projections.sessions6.user_agent_description,` +
` projections.sessions6.user_agent_header` +
` FROM projections.sessions6` +
` LEFT JOIN projections.login_names2 ON projections.sessions6.user_id = projections.login_names2.user_id AND projections.sessions6.instance_id = projections.login_names2.instance_id` +
` LEFT JOIN projections.users8_humans ON projections.sessions6.user_id = projections.users8_humans.user_id AND projections.sessions6.instance_id = projections.users8_humans.instance_id` +
` LEFT JOIN projections.users8 ON projections.sessions6.user_id = projections.users8.id AND projections.sessions6.instance_id = projections.users8.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedSessionsQuery = regexp.QuoteMeta(`SELECT projections.sessions5.id,` +
` projections.sessions5.creation_date,` +
` projections.sessions5.change_date,` +
` projections.sessions5.sequence,` +
` projections.sessions5.state,` +
` projections.sessions5.resource_owner,` +
` projections.sessions5.creator,` +
` projections.sessions5.user_id,` +
` projections.sessions5.user_checked_at,` +
expectedSessionsQuery = regexp.QuoteMeta(`SELECT projections.sessions6.id,` +
` projections.sessions6.creation_date,` +
` projections.sessions6.change_date,` +
` projections.sessions6.sequence,` +
` projections.sessions6.state,` +
` projections.sessions6.resource_owner,` +
` projections.sessions6.creator,` +
` projections.sessions6.user_id,` +
` projections.sessions6.user_checked_at,` +
` projections.login_names2.login_name,` +
` projections.users8_humans.display_name,` +
` projections.users8.resource_owner,` +
` projections.sessions5.password_checked_at,` +
` projections.sessions5.intent_checked_at,` +
` projections.sessions5.webauthn_checked_at,` +
` projections.sessions5.webauthn_user_verified,` +
` projections.sessions5.totp_checked_at,` +
` projections.sessions5.otp_sms_checked_at,` +
` projections.sessions5.otp_email_checked_at,` +
` projections.sessions5.metadata,` +
` projections.sessions6.password_checked_at,` +
` projections.sessions6.intent_checked_at,` +
` projections.sessions6.webauthn_checked_at,` +
` projections.sessions6.webauthn_user_verified,` +
` projections.sessions6.totp_checked_at,` +
` projections.sessions6.otp_sms_checked_at,` +
` projections.sessions6.otp_email_checked_at,` +
` projections.sessions6.metadata,` +
` COUNT(*) OVER ()` +
` FROM projections.sessions5` +
` LEFT JOIN projections.login_names2 ON projections.sessions5.user_id = projections.login_names2.user_id AND projections.sessions5.instance_id = projections.login_names2.instance_id` +
` LEFT JOIN projections.users8_humans ON projections.sessions5.user_id = projections.users8_humans.user_id AND projections.sessions5.instance_id = projections.users8_humans.instance_id` +
` LEFT JOIN projections.users8 ON projections.sessions5.user_id = projections.users8.id AND projections.sessions5.instance_id = projections.users8.instance_id` +
` FROM projections.sessions6` +
` LEFT JOIN projections.login_names2 ON projections.sessions6.user_id = projections.login_names2.user_id AND projections.sessions6.instance_id = projections.login_names2.instance_id` +
` LEFT JOIN projections.users8_humans ON projections.sessions6.user_id = projections.users8_humans.user_id AND projections.sessions6.instance_id = projections.users8_humans.instance_id` +
` LEFT JOIN projections.users8 ON projections.sessions6.user_id = projections.users8.id AND projections.sessions6.instance_id = projections.users8.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
sessionCols = []string{
@ -92,6 +99,10 @@ var (
"otp_email_checked_at",
"metadata",
"token",
"user_agent_fingerprint_id",
"user_agent_ip",
"user_agent_description",
"user_agent_header",
}
sessionsCols = []string{
@ -443,6 +454,10 @@ func Test_SessionPrepare(t *testing.T) {
testNow,
[]byte(`{"key": "dmFsdWU="}`),
"tokenID",
"fingerPrintID",
"1.2.3.4",
"agentDescription",
[]byte(`{"foo":["foo","bar"]}`),
},
),
},
@ -483,6 +498,12 @@ func Test_SessionPrepare(t *testing.T) {
Metadata: map[string][]byte{
"key": []byte("value"),
},
UserAgent: domain.UserAgent{
FingerprintID: gu.Ptr("fingerPrintID"),
IP: net.IPv4(1, 2, 3, 4),
Description: gu.Ptr("agentDescription"),
Header: http.Header{"foo": []string{"foo", "bar"}},
},
},
},
{

View File

@ -33,6 +33,7 @@ const (
type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
UserAgent *domain.UserAgent `json:"user_agent,omitempty"`
}
func (e *AddedEvent) Payload() interface{} {
@ -45,6 +46,7 @@ func (e *AddedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
func NewAddedEvent(ctx context.Context,
aggregate *eventstore.Aggregate,
userAgent *domain.UserAgent,
) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
@ -52,6 +54,7 @@ func NewAddedEvent(ctx context.Context,
aggregate,
AddedType,
),
UserAgent: userAgent,
}
}

View File

@ -0,0 +1,12 @@
package user
import "github.com/zitadel/zitadel/internal/api/grpc/server/middleware"
// OrganisationFromRequest implements deprecated [middleware.OrganisationFromRequest] interface.
// it will be removed before going GA (https://github.com/zitadel/zitadel/issues/6718)
func (r *AddHumanUserRequest) OrganisationFromRequest() *middleware.Organization {
return &middleware.Organization{
ID: r.GetOrganisation().GetOrgId(),
Domain: r.GetOrganisation().GetOrgDomain(),
}
}

Some files were not shown because too many files have changed in this diff Show More