Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
322a805
broker/himmelblau: move device registration helpers out of withmsentraid
nooreldeenmansour Jun 3, 2026
1ff45b1
broker/himmelblau: add bindings for Entra MFA login
nooreldeenmansour Jun 3, 2026
aeb8f7a
broker/himmelblau: cache broker apps by client configuration
nooreldeenmansour Jun 3, 2026
534462a
broker/providers/msentraid: add Graph fallback for group lookup
nooreldeenmansour Jun 2, 2026
3e76454
broker/providers/msentraid: implement Entra password auth hooks
nooreldeenmansour Jun 2, 2026
d7fe329
broker/password: split hashing from password storage
nooreldeenmansour Jun 2, 2026
bca675f
broker: add Entra password login with MFA follow-ups
nooreldeenmansour Jun 2, 2026
d9c85e5
e2e-tests: disable entra_password in provisioning
nooreldeenmansour Jun 3, 2026
db055e7
broker: verify the Entra MFA access-token signature
nooreldeenmansour Jun 22, 2026
0adbec1
himmelblau: disable DAG fallback in password+MFA init
nooreldeenmansour Jun 24, 2026
c634b49
himmelblau: replace MFA string matching with structured error codes
nooreldeenmansour Jun 25, 2026
6032db6
broker/pam: wrap granted response in {userinfo,message} envelope
nooreldeenmansour Jun 24, 2026
7b4c50b
pam: demote malformed granted message to a warning
nooreldeenmansour Jun 24, 2026
cdb0669
broker: attach caching notice after Entra password login
nooreldeenmansour Jun 23, 2026
22e5256
pam: avoid duplicate success notice on native clients
nooreldeenmansour Jun 23, 2026
353a099
deps(submodule): bump authd-oidc-brokers/third_party/libhimmelblau
nooreldeenmansour Jun 26, 2026
b162af9
e2e-tests: add TOTP helper and broker configuration resource
nooreldeenmansour Jun 29, 2026
420d675
e2e-tests: add entra_password login test for the register_device path
nooreldeenmansour Jun 29, 2026
d5496c8
e2e-tests: add entra_password login test for the client-secret path
nooreldeenmansour Jun 29, 2026
891c930
broker: never send client_secret for public-client OIDC flows
nooreldeenmansour Jun 29, 2026
4ef7ef8
e2e-tests: skip entra_password tests when not using the msentraid broker
nooreldeenmansour Jun 30, 2026
792cabb
broker: fail startup for unusable entra_password configs
nooreldeenmansour Jul 1, 2026
bba5348
broker: build refresh tokens without mutating the cached expiry
nooreldeenmansour Jul 1, 2026
4d9385b
AGENTS: document 72-character commit message line-length limit
nooreldeenmansour Jul 1, 2026
e0985dc
test: disable entra_password in daemon and dbusservice test configs
nooreldeenmansour Jul 1, 2026
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
3 changes: 3 additions & 0 deletions .github/workflows/e2e-tests-run.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ on:
required: false
E2E_MSENTRA_CLIENT_ID:
required: false
E2E_MSENTRA_CLIENT_SECRET:
required: false
E2E_MSENTRA_USERNAME:
required: false
E2E_MSENTRA_PASSWORD:
Expand Down Expand Up @@ -225,6 +227,7 @@ jobs:
export E2E_USER="${{ secrets.E2E_MSENTRA_USERNAME }}"
export E2E_PASSWORD="${{ secrets.E2E_MSENTRA_PASSWORD }}"
export TOTP_SECRET="${{ secrets.E2E_MSENTRA_TOTP_SECRET }}"
export AUTHD_MSENTRAID_CLIENT_SECRET="${{ secrets.E2E_MSENTRA_CLIENT_SECRET }}"
elif [ "${{ inputs.broker }}" = "authd-google" ]; then
export E2E_USER="${{ secrets.E2E_GOOGLE_USERNAME }}"
export E2E_PASSWORD="${{ secrets.E2E_GOOGLE_PASSWORD }}"
Expand Down
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ Explain why, not what — the diff shows what changed.
- For bug fixes, describe the observable symptom before the root cause
- Document non-obvious decisions and rejected alternatives
- One-liners are fine for mechanical changes; anything behavioral needs a body
- Try to keep the subject line at 72 characters or less; wrap body lines at 72 characters
(URLs that cannot be split are the only accepted exception)

Don't narrate your activity ("Fixed X as requested") or describe the diff
("Add null check before calling Process()").
Expand Down
26 changes: 16 additions & 10 deletions authd-oidc-brokers/cmd/authd-oidc/daemon/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,22 @@ func GenerateBrokerConfig(t *testing.T, p, providerURL string) {
require.NoError(t, err, "Setup: could not create parent broker configuration directory for tests")

brokerCfg := fmt.Sprintf(`
[authd]
name = %[1]s
brand_icon = broker_icon.png
dbus_name = com.ubuntu.authd.%[1]s
dbus_object = /com/ubuntu/authd/%[1]s

[oidc]
issuer = %[2]s
client_id = client_id
`, strings.ReplaceAll(t.Name(), "/", "_"), providerURL)
[authd]
name = %[1]s
brand_icon = broker_icon.png
dbus_name = com.ubuntu.authd.%[1]s
dbus_object = /com/ubuntu/authd/%[1]s

[oidc]
issuer = %[2]s
client_id = client_id

[flows]
# These tests don't exercise the entra_password flow, and the default
# (enabled) would fail startup validation under the withmsentraid tag
# because no client_secret or register_device is configured here.
entra_password = false
`, strings.ReplaceAll(t.Name(), "/", "_"), providerURL)
err = os.WriteFile(p, []byte(brokerCfg), 0600)
require.NoError(t, err, "Setup: could not create broker configuration for tests")
}
Expand Down
18 changes: 18 additions & 0 deletions authd-oidc-brokers/conf/variants/msentraid/broker.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ issuer = https://login.microsoftonline.com/<ISSUER_ID>/v2.0
## The client ID of the application registered in Entra ID.
client_id = <CLIENT_ID>

## Optional: Client secret for the OIDC application registered in Entra ID.
#client_secret = <CLIENT_SECRET>

## Force verification with the identity provider during login.
##
## When enabled, authd always verifies during login that the user still
Expand Down Expand Up @@ -93,3 +96,18 @@ client_id = <CLIENT_ID>
## (see 'owner' option) will be added to these groups.
## Example: owner_extra_groups = sudo,lpadmin
#owner_extra_groups =

[flows]
## Control which authentication flows are offered to users.
##
## device_auth: When true (default), users can authenticate with the
## device code flow (scanning a QR code or visiting a URL and entering
## a code).
#device_auth = true

## entra_password: When true (default), users can authenticate by entering
## their Microsoft Entra ID password directly, followed by MFA verification.
##
## Note: If both flows are disabled, no authentication will be available
## and users will not be able to log in.
#entra_password = true
Comment thread
adombeck marked this conversation as resolved.
Comment thread
nooreldeenmansour marked this conversation as resolved.
21 changes: 17 additions & 4 deletions authd-oidc-brokers/internal/broker/authmodes/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,27 @@ const (

// NewPassword is the ID of the new password configuration method.
NewPassword = "newpassword"

// EntraPassword is the ID of the Entra ID password + MFA authentication method.
EntraPassword = "entra_password"

// EntraMFAWait is the ID of the poll-based MFA follow-up mode.
EntraMFAWait = "entra_mfa_wait"

// EntraMFACode is the ID of the code-entry MFA follow-up mode.
EntraMFACode = "entra_mfa_code"
)

var (
// Label is a map of auth mode IDs to their display labels.
//nolint:gosec // G101: These are auth mode display labels, not credentials.
Label = map[string]string{
Password: "Local Password Authentication",
Device: "Device Authentication",
DeviceQr: "Device Authentication",
NewPassword: "Define your local password",
Password: "Local Password Authentication",
Device: "Device Authentication",
DeviceQr: "Device Authentication",
NewPassword: "Define your local password",
EntraPassword: "Entra ID password",
EntraMFAWait: "Waiting for MFA approval",
EntraMFACode: "Enter your MFA code",
}
)
7 changes: 7 additions & 0 deletions authd-oidc-brokers/internal/broker/authresponses.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ package broker

import "github.com/canonical/authd/authd-oidc-brokers/internal/providers/info"

// cachedPasswordMessage is the user-facing notice attached to a granted
// response after the user's Entra password is saved as the local password
// (during the Entra password + MFA flow). It is broker-owned so it can be
// localized independently of authd.
const cachedPasswordMessage = "Your local password has been set to your Entra password"

type isAuthenticatedDataResponse interface {
isAuthenticatedDataResponse()
}

// userInfoMessage represents the user information message that is returned to authd.
type userInfoMessage struct {
UserInfo info.User `json:"userinfo"`
Message string `json:"message,omitempty"`
}

func (userInfoMessage) isAuthenticatedDataResponse() {}
Expand Down
Loading
Loading