Skip to content

Commit

Permalink
feat: add support for Azure CIAM login (#1541)
Browse files Browse the repository at this point in the history
Adds support for [Azure's
CIAM](https://learn.microsoft.com/en-us/entra/external-id/customers/overview-customers-ciam)
login. This is a special B2B Azure account separate from the typical
tenant accounts and is meant to be used only when the expected issuer is
set to the CIAM tenant.

---------

Co-authored-by: Kang Ming <kang.ming1996@gmail.com>
  • Loading branch information
hf and kangmingtay committed Apr 23, 2024
1 parent 9594a53 commit 1cb4f96
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 3 deletions.
1 change: 0 additions & 1 deletion internal/api/errorcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ const (
ErrorCodeSMSSendFailed ErrorCode = "sms_send_failed"
ErrorCodeEmailNotConfirmed ErrorCode = "email_not_confirmed"
ErrorCodePhoneNotConfirmed ErrorCode = "phone_not_confirmed"
ErrorCodeReauthNonceMissing ErrorCode = "reauth_nonce_missing"
ErrorCodeSAMLRelayStateNotFound ErrorCode = "saml_relay_state_not_found"
ErrorCodeSAMLRelayStateExpired ErrorCode = "saml_relay_state_expired"
ErrorCodeSAMLIdPNotFound ErrorCode = "saml_idp_not_found"
Expand Down
12 changes: 10 additions & 2 deletions internal/api/provider/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,16 @@ type azureProvider struct {
}

var azureIssuerRegexp = regexp.MustCompile("^https://login[.]microsoftonline[.]com/([^/]+)/v2[.]0/?$")
var azureCIAMIssuerRegexp = regexp.MustCompile("^https://[a-z0-9-]+[.]ciamlogin[.]com/([^/]+)/v2[.]0/?$")

func IsAzureIssuer(issuer string) bool {
return azureIssuerRegexp.MatchString(issuer)
}

func IsAzureCIAMIssuer(issuer string) bool {
return azureCIAMIssuerRegexp.MatchString(issuer)
}

// NewAzureProvider creates a Azure account provider.
func NewAzureProvider(ext conf.OAuthProviderConfiguration, scopes string) (OAuthProvider, error) {
if err := ext.ValidateOAuth(); err != nil {
Expand All @@ -62,7 +67,7 @@ func NewAzureProvider(ext conf.OAuthProviderConfiguration, scopes string) (OAuth
if ext.URL != "" {
expectedIssuer = authHost + "/v2.0"

if !IsAzureIssuer(expectedIssuer) || expectedIssuer == IssuerAzureCommon || expectedIssuer == IssuerAzureOrganizations {
if !IsAzureIssuer(expectedIssuer) || !IsAzureCIAMIssuer(expectedIssuer) || expectedIssuer == IssuerAzureCommon || expectedIssuer == IssuerAzureOrganizations {
// in tests, the URL is a local server which should not
// be the expected issuer
// also, IssuerAzure (common) never actually issues any
Expand Down Expand Up @@ -121,7 +126,10 @@ func (g azureProvider) GetUserData(ctx context.Context, tok *oauth2.Token) (*Use
return nil, err
}

if !IsAzureIssuer(issuer) {
// Allow basic Azure issuers, except when the expected issuer
// is configured to be the Azure CIAM issuer, allow CIAM
// issuers to pass.
if !IsAzureIssuer(issuer) && (IsAzureCIAMIssuer(g.ExpectedIssuer) && !IsAzureCIAMIssuer(issuer)) {
return nil, fmt.Errorf("azure: ID token issuer not valid %q", issuer)
}

Expand Down

0 comments on commit 1cb4f96

Please sign in to comment.