feat(oidc): allow additional audience based on scope in device auth (#7685)

feat(oidc): allow additional audience based on scope
This commit is contained in:
Tim Möhlmann
2024-04-03 09:06:21 +03:00
committed by GitHub
parent 2d25244c77
commit 5b3946b67e
10 changed files with 61 additions and 24 deletions

View File

@@ -37,6 +37,10 @@ var (
name: projection.DeviceAuthRequestColumnScopes,
table: deviceAuthRequestTable,
}
DeviceAuthRequestColumnAudience = Column{
name: projection.DeviceAuthRequestColumnAudience,
table: deviceAuthRequestTable,
}
DeviceAuthRequestColumnCreationDate = Column{
name: projection.DeviceAuthRequestColumnCreationDate,
table: deviceAuthRequestTable,
@@ -61,6 +65,7 @@ type DeviceAuth struct {
UserCode string
Expires time.Time
Scopes []string
Audience []string
State domain.DeviceAuthState
Subject string
UserAuthMethods []domain.UserAuthMethodType
@@ -109,6 +114,7 @@ var deviceAuthSelectColumns = []string{
DeviceAuthRequestColumnDeviceCode.identifier(),
DeviceAuthRequestColumnUserCode.identifier(),
DeviceAuthRequestColumnScopes.identifier(),
DeviceAuthRequestColumnAudience.identifier(),
}
func prepareDeviceAuthQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*domain.AuthRequestDevice, error)) {
@@ -116,7 +122,8 @@ func prepareDeviceAuthQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
func(row *sql.Row) (*domain.AuthRequestDevice, error) {
dst := new(domain.AuthRequestDevice)
var (
scopes database.TextArray[string]
scopes database.TextArray[string]
audience database.TextArray[string]
)
err := row.Scan(
@@ -124,6 +131,7 @@ func prepareDeviceAuthQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
&dst.DeviceCode,
&dst.UserCode,
&scopes,
&audience,
)
if errors.Is(err, sql.ErrNoRows) {
return nil, zerrors.ThrowNotFound(err, "QUERY-Sah9a", "Errors.DeviceAuth.NotExisting")
@@ -132,6 +140,7 @@ func prepareDeviceAuthQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
return nil, zerrors.ThrowInternal(err, "QUERY-Voo3o", "Errors.Internal")
}
dst.Scopes = scopes
dst.Audience = audience
return dst, nil
}
}

View File

@@ -29,6 +29,7 @@ func (m *DeviceAuthReadModel) Reduce() error {
m.UserCode = e.UserCode
m.Expires = e.Expires
m.Scopes = e.Scopes
m.Audience = e.Audience
m.State = e.State
case *deviceauth.ApprovedEvent:
m.State = domain.DeviceAuthStateApproved

View File

@@ -55,6 +55,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
ctx,
deviceauth.NewAggregate("device1", "instance1"),
"client1", "device1", "user-code", timestamp, []string{"foo", "bar"},
[]string{"projectID", "clientID"},
)),
),
),
@@ -64,6 +65,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
UserCode: "user-code",
Expires: timestamp,
Scopes: []string{"foo", "bar"},
Audience: []string{"projectID", "clientID"},
State: domain.DeviceAuthStateInitiated,
},
},
@@ -75,6 +77,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
ctx,
deviceauth.NewAggregate("device1", "instance1"),
"client1", "device1", "user-code", timestamp, []string{"foo", "bar"},
[]string{"projectID", "clientID"},
)),
eventFromEventPusher(deviceauth.NewApprovedEvent(
ctx,
@@ -90,6 +93,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
UserCode: "user-code",
Expires: timestamp,
Scopes: []string{"foo", "bar"},
Audience: []string{"projectID", "clientID"},
State: domain.DeviceAuthStateApproved,
Subject: "user1",
UserAuthMethods: []domain.UserAuthMethodType{domain.UserAuthMethodTypePasswordless},
@@ -104,6 +108,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
ctx,
deviceauth.NewAggregate("device1", "instance1"),
"client1", "device1", "user-code", timestamp, []string{"foo", "bar"},
[]string{"projectID", "clientID"},
)),
eventFromEventPusher(deviceauth.NewCanceledEvent(
ctx,
@@ -118,6 +123,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
UserCode: "user-code",
Expires: timestamp,
Scopes: []string{"foo", "bar"},
Audience: []string{"projectID", "clientID"},
State: domain.DeviceAuthStateDenied,
},
},
@@ -129,6 +135,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
ctx,
deviceauth.NewAggregate("device1", "instance1"),
"client1", "device1", "user-code", timestamp, []string{"foo", "bar"},
[]string{"projectID", "clientID"},
)),
eventFromEventPusher(deviceauth.NewCanceledEvent(
ctx,
@@ -143,6 +150,7 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
UserCode: "user-code",
Expires: timestamp,
Scopes: []string{"foo", "bar"},
Audience: []string{"projectID", "clientID"},
State: domain.DeviceAuthStateExpired,
},
},
@@ -161,14 +169,15 @@ func TestQueries_DeviceAuthByDeviceCode(t *testing.T) {
const (
expectedDeviceAuthQueryC = `SELECT` +
` projections.device_auth_requests.client_id,` +
` projections.device_auth_requests.device_code,` +
` projections.device_auth_requests.user_code,` +
` projections.device_auth_requests.scopes` +
` FROM projections.device_auth_requests`
` projections.device_auth_requests1.client_id,` +
` projections.device_auth_requests1.device_code,` +
` projections.device_auth_requests1.user_code,` +
` projections.device_auth_requests1.scopes,` +
` projections.device_auth_requests1.audience` +
` FROM projections.device_auth_requests1`
expectedDeviceAuthWhereUserCodeQueryC = expectedDeviceAuthQueryC +
` WHERE projections.device_auth_requests.instance_id = $1` +
` AND projections.device_auth_requests.user_code = $2`
` WHERE projections.device_auth_requests1.instance_id = $1` +
` AND projections.device_auth_requests1.user_code = $2`
)
var (
@@ -179,12 +188,14 @@ var (
"device1",
"user-code",
database.TextArray[string]{"a", "b", "c"},
[]string{"projectID", "clientID"},
}
expectedDeviceAuth = &domain.AuthRequestDevice{
ClientID: "client-id",
DeviceCode: "device1",
UserCode: "user-code",
Scopes: []string{"a", "b", "c"},
Audience: []string{"projectID", "clientID"},
}
)

View File

@@ -11,12 +11,13 @@ import (
)
const (
DeviceAuthRequestProjectionTable = "projections.device_auth_requests"
DeviceAuthRequestProjectionTable = "projections.device_auth_requests1"
DeviceAuthRequestColumnClientID = "client_id"
DeviceAuthRequestColumnDeviceCode = "device_code"
DeviceAuthRequestColumnUserCode = "user_code"
DeviceAuthRequestColumnScopes = "scopes"
DeviceAuthRequestColumnAudience = "audience"
DeviceAuthRequestColumnCreationDate = "creation_date"
DeviceAuthRequestColumnChangeDate = "change_date"
DeviceAuthRequestColumnSequence = "sequence"
@@ -44,6 +45,7 @@ func (*deviceAuthRequestProjection) Init() *old_handler.Check {
handler.NewColumn(DeviceAuthRequestColumnDeviceCode, handler.ColumnTypeText),
handler.NewColumn(DeviceAuthRequestColumnUserCode, handler.ColumnTypeText),
handler.NewColumn(DeviceAuthRequestColumnScopes, handler.ColumnTypeTextArray),
handler.NewColumn(DeviceAuthRequestColumnAudience, handler.ColumnTypeTextArray),
handler.NewColumn(DeviceAuthRequestColumnCreationDate, handler.ColumnTypeTimestamp),
handler.NewColumn(DeviceAuthRequestColumnChangeDate, handler.ColumnTypeTimestamp),
handler.NewColumn(DeviceAuthRequestColumnSequence, handler.ColumnTypeInt64),
@@ -89,6 +91,7 @@ func (p *deviceAuthRequestProjection) reduceAdded(event eventstore.Event) (*hand
handler.NewCol(DeviceAuthRequestColumnDeviceCode, e.DeviceCode),
handler.NewCol(DeviceAuthRequestColumnUserCode, e.UserCode),
handler.NewCol(DeviceAuthRequestColumnScopes, e.Scopes),
handler.NewCol(DeviceAuthRequestColumnAudience, e.Audience),
handler.NewCol(DeviceAuthRequestColumnCreationDate, e.CreationDate()),
handler.NewCol(DeviceAuthRequestColumnChangeDate, e.CreationDate()),
handler.NewCol(DeviceAuthRequestColumnSequence, e.Sequence()),