Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion bootstrap/backends/ldap/ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,18 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) {
return nil, fmt.Errorf("invalid --encryption-secret parameter value for identifier: %v", err)
}

// Expose the identifier in the managers registry so other managers (e.g.
// signedlogin) can access it without creating a second instance.
bs.Managers().Set("identifier", activeIdentifier)

identityManagerConfig := &identity.Config{
SignInFormURI: fullSignInFormURL,
SignedOutURI: fullSignedOutEndpointURL,

Logger: logger,

ScopesSupported: config.Config.AllowedScopes,
ScopesSupported: config.Config.AllowedScopes,
AllowSignedLogin: config.Config.AllowClientSignedLogins,
}

identifierIdentityManager := managers.NewIdentifierIdentityManager(identityManagerConfig, activeIdentifier)
Expand Down
7 changes: 6 additions & 1 deletion bootstrap/backends/libregraph/libregraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,18 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) {
return nil, fmt.Errorf("invalid --encryption-secret parameter value for identifier: %v", err)
}

// Expose the identifier in the managers registry so other managers (e.g.
// signedlogin) can access it without creating a second instance.
bs.Managers().Set("identifier", activeIdentifier)

identityManagerConfig := &identity.Config{
SignInFormURI: fullSignInFormURL,
SignedOutURI: fullSignedOutEndpointURL,

Logger: logger,

ScopesSupported: config.Config.AllowedScopes,
ScopesSupported: config.Config.AllowedScopes,
AllowSignedLogin: config.Config.AllowClientSignedLogins,
}

identifierIdentityManager := managers.NewIdentifierIdentityManager(identityManagerConfig, activeIdentifier)
Expand Down
5 changes: 5 additions & 0 deletions bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ func (bs *bootstrap) initialize(settings *Settings) error {
logger.Infoln("client controlled guests are enabled")
}

bs.config.Config.AllowClientSignedLogins = settings.AllowClientSignedLogins
if bs.config.Config.AllowClientSignedLogins {
logger.Infoln("client controlled signed logins are enabled")
}

bs.config.Config.AllowDynamicClientRegistration = settings.AllowDynamicClientRegistration
if bs.config.Config.AllowDynamicClientRegistration {
logger.Infoln("dynamic client registration is enabled")
Expand Down
1 change: 1 addition & 0 deletions bootstrap/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Settings struct {
TrustedProxy []string
AllowScope []string
AllowClientGuests bool
AllowClientSignedLogins bool
AllowDynamicClientRegistration bool
EncryptionSecretFile string
Listen string
Expand Down
1 change: 1 addition & 0 deletions cmd/licod/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func commandServe() *cobra.Command {
serveCmd.Flags().StringArrayVar(&cfg.TrustedProxy, "trusted-proxy", nil, "Trusted proxy IP or IP network (can be used multiple times)")
serveCmd.Flags().StringArrayVar(&cfg.AllowScope, "allow-scope", nil, "Allow OAuth 2 scope (can be used multiple times, if not set default scopes are allowed)")
serveCmd.Flags().BoolVar(&cfg.AllowClientGuests, "allow-client-guests", false, "Allow sign in of client controlled guest users")
serveCmd.Flags().BoolVar(&cfg.AllowClientSignedLogins, "allow-client-signed-logins", false, "Allow sign in of client controlled signed login users")
serveCmd.Flags().BoolVar(&cfg.AllowDynamicClientRegistration, "allow-dynamic-client-registration", false, "Allow dynamic OAuth2 client registration")
serveCmd.Flags().Uint64Var(&cfg.AccessTokenDurationSeconds, "access-token-expiration", 60*10, "Expiration time of access tokens in seconds since generated") // 10 Minutes.
serveCmd.Flags().Uint64Var(&cfg.IDTokenDurationSeconds, "id-token-expiration", 60*60, "Expiration time of id tokens in seconds since generated") // 1 Hour.
Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ type Config struct {

AllowedScopes []string
AllowClientGuests bool
AllowClientSignedLogins bool
AllowDynamicClientRegistration bool
}
27 changes: 14 additions & 13 deletions identifier/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,27 +269,26 @@ func (i *Identifier) ErrorPage(rw http.ResponseWriter, code int, title string, m
utils.WriteErrorPage(rw, code, title, message)
}

// SetUserToLogonCookie serializes the provided user into an encrypted string
// and sets it as cookie on the provided http.ResponseWriter.
func (i *Identifier) SetUserToLogonCookie(ctx context.Context, rw http.ResponseWriter, user *IdentifiedUser) error {
// WriteLogonCookie serializes the provided user into an encrypted string and
// sets it as a logon cookie without firing any callbacks. Use this when the
// cookie must be written mid-flow (e.g. inside an authorize handler) where
// the caller is responsible for updating browser state separately.
func (i *Identifier) WriteLogonCookie(rw http.ResponseWriter, user *IdentifiedUser) error {
loggedOn, logonAt := user.LoggedOn()
if !loggedOn {
return fmt.Errorf("refused to set cookie for not logged on user")
}

// Add standard claims.
claims := jwt.Claims{
Issuer: user.BackendName(),
Audience: audienceMarker,
Subject: user.Subject(),
IssuedAt: jwt.NewNumericDate(logonAt),
}
// Add expiration, if set.
if user.expiresAfter != nil {
claims.Expiry = jwt.NewNumericDate(*user.expiresAfter)
}

// Additional claims.
userClaims := map[string]interface{}(user.Claims())
if sessionRef := user.SessionRef(); sessionRef != nil {
userClaims[SessionIDClaim] = *sessionRef
Expand All @@ -304,25 +303,27 @@ func (i *Identifier) SetUserToLogonCookie(ctx context.Context, rw http.ResponseW
userClaims[LockedScopesClaim] = strings.Join(lockedScopes, " ")
}

// Serialize and encrypt cookie value.
serialized, err := jwt.Encrypted(i.encrypter).Claims(claims).Claims(userClaims).CompactSerialize()
if err != nil {
return err
}

// Set cookie.
err = i.setLogonCookie(rw, serialized)
if err != nil {
return i.setLogonCookie(rw, serialized)
}

// SetUserToLogonCookie serializes the provided user into an encrypted string,
// sets it as cookie on the provided http.ResponseWriter, and fires the
// onSetLogon callbacks.
func (i *Identifier) SetUserToLogonCookie(ctx context.Context, rw http.ResponseWriter, user *IdentifiedUser) error {
if err := i.WriteLogonCookie(rw, user); err != nil {
return err
}
// Trigger callbacks.
for _, f := range i.onSetLogonCallbacks {
err = f(ctx, rw, user)
if err != nil {
if err := f(ctx, rw, user); err != nil {
return err
}
}

return nil
}

Expand Down
6 changes: 6 additions & 0 deletions identifier/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ func (u *IdentifiedUser) LoggedOn() (bool, time.Time) {
return !u.logonAt.IsZero(), u.logonAt
}

// SetLogonAt sets the logon timestamp, marking the user as logged on. Used by
// flows that authenticate without a password challenge (e.g. signed login).
func (u *IdentifiedUser) SetLogonAt(t time.Time) {
u.logonAt = t
}

// SessionRef returns the accociated users underlaying session reference.
func (u *IdentifiedUser) SessionRef() *string {
return u.sessionRef
Expand Down
3 changes: 3 additions & 0 deletions identity/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ type Config struct {

ScopesSupported []string

// AllowSignedLogin enables the signed JWT auto sign-in flow.
AllowSignedLogin bool

Logger logrus.FieldLogger
}
Loading
Loading