Getting Email and Manager ID in SAML attributes from Azure AD - azure-active-directory

I have successfully created a single sign on integration from Azure AD to my app by creating an Enterprise application using SAML SSO. My issue now is that certain attributes are either not being passed over as claims as expected, or there is no obvious way of adding them.
Firstly: the email has been filled in in the user's profile:
But even though it has been mapped in the SAML Token Attributes (twice, just to be sure) ...
... the primary email does not get passed in the SAML (yet the alternate/other email does):
<AttributeStatement>
<Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid">
<AttributeValue>7204392b-...</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
<AttributeValue>05f0140b-...</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/displayname">
<AttributeValue>Joe Bloggs</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/identityprovider">
<AttributeValue>https://sts.windows.net/7204392b-...</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/claims/authnmethodsreferences">
<AttributeValue>http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
<AttributeValue>Joe</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
<AttributeValue>Bloggs</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
<AttributeValue>Joe.Bloggs#EXAMPLE.onmicrosoft.com</AttributeValue>
</Attribute>
<Attribute Name="jobtitle">
<AttributeValue>my job title</AttributeValue>
</Attribute>
<Attribute Name="otheremail">
<AttributeValue>Joe.Bloggs#example.net</AttributeValue>
</Attribute>
</AttributeStatement>
Finally, I see no way of passing across users' Manager IDs. It is filled in in the user's profile ...
... but there is no way of mapping this to a SAML attribute (nothing resembling Manager ID is in the list of choices):

The Manager attribute isn't yet available as a source for claims, as are a number of other user attributes you'd expect to be able to use. We have work in our backlog to make these available. Look out for updates in the documentation later this year.
For the issue with the email attribute, you should be able to emit it as a claim if it is populated. It will only be populated if the user is an office365 user with an Office365 mailbox or if they are synchronized from a Windows Active Directory domain with a mailbox Please check using the powershell get-azureaduser whether the mail attribute is set. The claims mapping algorithm will ignore a claim when the source is empty.

Related

Azure AD B2C: Persisting a default value for a claim during local sign up

In my application I'm trying to use a custom user attribute, extension_Role, that should be persisted to the user during sign up.
I'd like one class of user, say "Customer" to sign-up via a mobile application and not need to provide the Role field, just default it to "Customer" behind the scenes. A second class of user will sign-up using a web app, and I'd like them to be able to select the role from a drop-down, say "Support", "Admin", etc... My plan is to provide two versions of SignUpOrSignin.xml to handle this.
Using the sample policy files Microsoft provide in the starter pack I've defined my custom ClaimType (with no UserInputType) in TrustFrameworkBase.xml and configured the client and object IDs. I've also modified the AAD-UserWriteUsingLogonEmail TechnicalProfile to persist the claim.
I'm stuck with actually persisting a default value. I've tried adding:
<OutputClaim ClaimTypeReferenceId="extension_Role" AlwaysUseDefaultValue="true" DefaultValue="Customer" />
to SignUpOrSignin.xml, however when I run the flow, I get a 500 error once I click on sign up. I think this is because it is expecting that the extension_Role field should be filled in by the user.
The only way I've been able to persist extension_Role is by adding it to the LocalAccountSignUpWithLogonEmail TechnicalProfile in TrustFrameworkBase.xml. For example:
<OutputClaim ClaimTypeReferenceId="extension_Role" DefaultValue="Customer"/>
However since this in the base file, it is shared by all login flows, which would prevent me from setting different values for different sign up flows.
What is the correct way to model this kind of dual sign-up flow?
You must specify the UserInputType when you collect information from the user by using a self-asserted technical profile. See reference here. It is why you get 500 error.
Please note that the Claim you set in SignUpOrSignin.xml (with <OutputClaim ClaimTypeReferenceId="extension_Role" AlwaysUseDefaultValue="true" DefaultValue="Customer" />) will be only returned after your sign-up at that time. The custom attribute won't be stored into Azure AD. That means when you want to query the custom attribute later, you won't find it.
So you have to set the value of extension_Role in Base policy file rather than SignUpOrSignin.xml.
In this scene, you should define two TechnicalProfiles for LocalAccountSignUpWithLogonEmail and one accepts user input, and the other one sets DefaultValue for your custom claim.
Then reference them separately from your two SignUpOrSignin.xml.

Is it possible to pass groups to B2C from federated AD to Azure AD B2C

I have an application running on B2C as part of customer deployment we federate with the customers AD so they can log in with their own corporate identity.
We then create matching groups in the B2C to control behaviors in the app.
We have a request that a customer wants to create the groups in their AD and then pass it across so that they can manage their users and access in one place.
I can see how I can add the claims I want when setting up a user flow but I cant see any option for groups. Is it possible to do or do i have to query the external AD (matching the way I query for groups in the B2C directory)
Thanks
While technically possible, I still have question for the benefit of doing this.
I will try to briefly describe how this would technically work. If not clear - I will have to summ-it on Github. This is only possible using custom policy. So you have to follow: https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-technical-profile
Edit the Menifest of the application registration in federated AAD. There you have to indicate that you require group membership claim:
"groupMembershipClaims": "All",
Extend the claims schema in your custom policy extensions by adding a new claim:
<ClaimsSchema>
<ClaimType Id="idpGroupMemberships">
<DisplayName>Group Memberships in the IdP</DisplayName>
<DataType>stringCollection</DataType>
<UserHelpText>This is read only for the user</UserHelpText>
</ClaimType>
</ClaimsSchema>
Later in the technical profile, copy the incoming groups claim into your outputclaims:
<OutputClaims>
...
<OutputClaim ClaimTypeReferenceId="idpGroupMemberships" PartnerClaimType="groups" />
</OutputClaims>
Finally, you have to include that new claim in your relying party policy:
<RelyingParty>
<DefaultUserJourney ReferenceId="SuSiLocalFbStaykovNet" />
<TechnicalProfile Id="PolicyProfile">
<DisplayName>PolicyProfile</DisplayName>
<Protocol Name="OpenIdConnect" />
<OutputClaims>
...
<OutputClaim ClaimTypeReferenceId="idpGroupMemberships" />
</OutputClaims>
<SubjectNamingInfo ClaimType="sub" />
</TechnicalProfile>
</RelyingParty>
Using this approach you will get the Groups as GUIDs (these will be the objec IDs of the groups in federated AAD). If you want to get the Groups as names and not GUIDs, it is only partially supported and more complicated. Check out this doc here: https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-fed-group-claims#configure-the-azure-ad-application-registration-for-group-attributes
Not exactly an answer but some insight why this might be useful.
While technically possible, I still have question for the benefit of doing this.
I have a smaller organization and a public facing B2C offer and a management UI that handles the customer requests. Some sensitive data is on an internal SQL server and we have for historical reasons and some elder software an on-premise AD. I have now running AAD B2B with hybrid connection and SQL via hybrid connection. Customers running on B2C. Because it's technically just one app, it's also just one login --> ADB2C with a social IDP pointing to AADB2B, that internally is backed by the on-premise AAD.
That all works very well and is exactly what we need. I came here with the same question as the OP to forward the security group information to the token to handle some access restrictions in the management UI.
Hence, for me the scenario makes absolutely sense. Just my 2 cent.

How to submit an add-in to AppSource that requires an authentication with OAuth 2.0?

I'm developing an add-in that integrates with a product of the company that i work. So to use the add-in the customer need to have a system login which Microsoft would not have.
What are the guidelines for submitting an add-in of this nature?
Must i indicate something in the manifest file?
<Hosts>
<Host Name="Workbook" />
</Hosts>
<Requirements>
<Sets DefaultMinVersion="1.2">
<Set Name="ExcelApi" MinVersion="1.2"/>
</Sets>
</Requirements>
<DefaultSettings>
<SourceLocation DefaultValue="" />
</DefaultSettings>
It sounds like our Enterprise policies may be applicable to your scenario. Please see this blog post for more information.
When you are ready to submit to AppSource, you will need to ensure you provide a system login in the test notes to ensure the validation team can fully test your submission.

Manage user restrictions to different apps within a single B2C Tenant

Within a single Azure AD B2C Tenant I have a directory of Users. Also, I have 2 Applications registered. Call them App1 and App2.
Assume that a User has registered his/her Account coming from (and being redirected back to) App1, now that the user is in the common User directory, he/she could also sign in to App2 and I can't do anything about it.
It doesn't make much sense to me, and I need to restrict it. How can I control which Apps the Users can access? A User could have access to any amount of registered Applications. I can't seem to find that in the Azure Portal...
Of course I can apply any solution also on App side, e.g. by checking some claim or something, but still, I need to know how to manage such restrictions. (this could be a fully custom way)
You would have to implement in B2C exactly what you said you'd implement in the app
by checking some claim or something
Apart of your B2C user journey you would introduce a precondition to check whether a claim exists or equals a certain value. This would require custom policies. There isn't an easy way to "error" out, but you could create a self asserted page that just shows an error message with a dummy input claim.
You're much better off building this logic in your application.
<OrchestrationStep Order="3" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="false">
<Value>app_permission</Value>
<Value>portalapp</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="AppRestrictionExchange" TechnicalProfileReferenceId="TechnicalProfileHere" />
</ClaimsExchanges>
</OrchestrationStep>

Azure Active Directory B2C custom error page is ignored

We have a custom Azure AD B2C Sign-in/Sign-up policy in place (SAML-based, the default policy doesn't do what we need).
We're able to customize the page UI as expected, via a content definition like:
<ContentDefinition Id="api.localaccountsignin">
<LoadUri>https://example.com/SAMLSignIn.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:selfasserted:1.1.0</DataUri>
<Metadata>
<Item Key="DisplayName">Local account sign in page</Item>
</Metadata>
</ContentDefinition>
But attempting to customize the error page, via:
<ContentDefinition Id="api.error">
<LoadUri>https://example.com/SAMLErrorPage.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:globalexception:1.1.0</DataUri>
<Metadata>
<Item Key="DisplayName">Error page</Item>
</Metadata>
</ContentDefinition>
changes nothing. The SAMLSignIn.html page is still used (albeit with the contents of whatever signin error occurred). This happens whether we test with invalid user names, bad passwords, whatever.
Even setting
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
in the associated <ValidationTechnicalProfile> doesn't force the error.
The user journey as seen in ApplicationInsights shows only a Web.TPEngine.Providers.BadArgumentRetryNeededException; no other errors or exceptions are logged.
How can we cause a custom error page to be used on login failure (for whatever reason)?
The documentation, such as it is, seems to imply we're doing the right thing (as does How to Create a Custom Error Page in Azure AD B2C | Custom Policies). I can't find any suggestion that we need to specify custom error handling in the UserJourney, nor any means by which we could do so if we wanted.
To summarize:
You are using local account sign-in with SAML issuer. This makes sign-in process happen on Azure AD B2C sign-in page. The error messages you see are just regular validation error messages. This all happens on the sign-in page, not the error page. Error content is only used by the engine when an unhandled exception breaks the execution of the user journey. Which is not the case with a regular sign-in.
Your option to customize validation errors are limited to using pure CSS on the sign-in page.
A really complex customization is demonstrated here
The document describing UI customization in general, is here
And UI customization using custom policy here
At your best effort you will come with some nice error messages like these:

Resources