I'm trying to extract a single email address from an array of email addresses (stored in the otherEmails attribute). I thought I could use the GetSingleValueFromJsonArray claims transformation. But, I get the following error:
The InputClaims mismatched in ClaimsTransformation with id
"GetEmailFromJson" with TransformationMethod
"GetSingleValueFromJsonArray". The following InputClaims were declared
in the Policy but were not expected by the TransformMethod:
[StringCollection]inputJsonClaim. The following InputClaims were
expected by the TransformMethod but were not declared in the Policy:
[String]inputJsonClaim.
It's complaining that my input is a collection of strings -which it is. The error says it wants a 'string' as input. The documentation also states that it wants a string. But then I'm confused how this should ever work with an array, as the name implies.
Essentially, I just want to return the email address in the id_token when using OpenID Connect. But with B2C it seems I can't set the mail field and it's null when I query for it. So, I've taken to using the otherEmails field. But I really only plan on storing a single email in it. Thus, I want to return the email claim as a single value claim, and not an array.
Update
After a bit more digging, I realized I can accomplish my goal without using a ClaimsTransformation. I can just map the 'signInNames.emailAddress' to 'email'.
<OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email"/>
You can use the GetSingleItemFromStringCollection claims transformation to get the first item in the string collection.
Related
I am trying to pass {Culture:LanguageName} and {OAUTH-KV:key} to json body in post request using GenerateJson transfomration method. Unfortunately I am not able to pass it to json, both values are resolved to value "undefined" and skipped during json generation. I managed to make it work but only with
<UserInputType>Readonly</UserInputType>
in claim type.
I don't want to display those values in UI form so leaving readonly input type is not an option for me.
added two ClaimType for each param I want to include in my json
Setup another technical profile with <Item Key="IncludeClaimResolvingInClaimsHandling">true</Item> metadata and included AlwaysUseDefaultValue="true" DefaultValue="{Culture:LanguageName}" in InputClaim
used it in my user journey as first step with ClaimsExchange
Used claims setup in first step in my json transformation
I'm working on a registration flow that I'm having difficulty with. I've got a self asserted profile to collect some data, and it's got validation profile that calls a REST endpoint. The REST endpoint passes back, among other things, a claim indicating if there's an error (boolean) and if there is, an error type (string). I've been back and forth with possible solutions, but I haven't been able to figure out how to do what amounts to a case statement - that is, if the error is "Not Found", load content from {notfoundurl} (via a technical profile's ContentDefinitionReferenceId) and display to the user; if the error is "Partial Match", load content from {partialmatchurl} and display to the user, and if everything seems to be in order, allow the user to enter a username and password to register. Is there an elegant solution to this?
I'm trying to query for some SP list items, all is working fine except I can't seem to expand a custom column of type Person.
I can see the createdBy and lastModifiedBy expanded and even includes the AAD user id, which is great and also leads me to think what I want is possible!
But mine is a custom column.
I'm running this and can only seem to get the SP user list id and the user's display name...neither of which are much use.
/items?expand=fields(select=UserLookupId,User)
Ideally I'd like to get the AAD user id as per createdBy and modifiedBy field, but the email would suffice.
Otherwise the only way I can see is to query the User Information List (using the UserLookupId) to get the email?
Thanks
This appears to be correct assumption:
Otherwise the only way I can see is to query the User Information List
(using the UserLookupId) to get the email?
for non-system user fields, it is indeed a way to go, but there are some distinctions whether user field is multi-valued or single-valued.
If Approvers is a multi-valued user field, then the following query:
https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items?$expand=fields($select=Approvers)
returns email and id properties along with displayName property for user field value.
While for single-valued user field only id (available via {userfield}LookupId property) and displayName properties could be requested via items endpoint, for example:
https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items?$expand=fields($select=Approver,ApproverLookupId)
So, indeed User Information List needs to be utilized to request additional user properties, for example:
https://graph.microsoft.com/v1.0/sites/root/lists('User Information List')/items/{item-id}/?$expand=fields($select=Email)
where item-id corresponds to user field lookup id
This was my experience modifying the
Build Angular single-page apps with Microsoft Graph. In the examples below, I changed my id's out with the default text.
Here is
The Finished Project on thier github
In Graph Explorer, this worked. You can verify it at the Microsoft Graph Explorer.
https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items?expand=fields($select=id,Title)
In the app/graph.service.ts in the app, this did not work. Even though you would expect it to based on the graph explorer.
.api('/sites/{site-id}/lists/{list-id}/items?fields($select=id,Title)')
Changing the app/graph.service.ts api call worked.
.api('/sites/{site-id}/lists/{list-id}/items?')
.expand('fields($select=id,Title)')
The result looked like this:
fields: {
#odata.etag: ""d6f5b6ea-9f90-452d-98ba-e838f58d3359,1"",
Title: "IT SPECIALIST (MID)",
id: "20"
}
Here's an example site id:
some.sharepoint.com,9dk062b-2e54-4e4f-b71a-cdb74f42cc44,c6cf6b0a-cc7c-41fd-a76a-ef8f97e8a22f
Here's an example list id.
8eg8c29a-5555-4cfc-bfa4-0e907488f781
The end url won't have any {} in it.
If the same output claim is defined in multiple technical profiles, what is the expected behavior?
Particularly if a technical profile emits an output claim and another technical profile that executes later defines the same output claim but does not emit one at run time, what is the expected behavior?
If there are two different OrchestrationSteps, each containing a TechnicalProfile that emits the same claim, then the TechnicalProfile from the later step will "overwrite" the value of the claim if such a claim is emitted.
Lets take a specific (although somewhat made-up) example.
Step 1 uses a TechnicalProfile for a SelfAsserted page that asks the user for their first name via "OutputClaim ClaimTypeReferenceId="givenName"" . The user fills in the name "John" on this page, and continues.
Step 2 uses a TechnicalProfile for a ClaimsExchange with Google, which may also emit a first name via "OutputClaim ClaimTypeReferenceId="givenName"".
However, it is possible that the user did or did not register their first name when creating their account at Google. If the first name is available (lets say with the name "Lingeshwaran"), then Google will emit that claim, and B2C will consume it. In this case, the final resulting value after step 2 for givenName will be "Lingeshwaran".
If the user did not fill in their first name when creating their Google account, then it will be missing from the claims that Google emits in their token. As a result, the existing "givenName" claim will not be overwritten, and the resulting value after step 2 for givenName will be "John".
I have two questions concerning ASP.Identity 2.0 "GenerateEmailConfirmationToken/GenerateEmailConfirmationTokenAsync" methods.
// Generate token
var token = Url.Encode(await UserManager.GenerateEmailConfirmationTokenAsync(user.Id));
Is this token stored in the database? I guess it should. But in which field? I just find "PasswordHash" and "SecurityStamp" on the User table. Both don't seem to match.
I was under the impression that once I generate an email token, the EmailConfirmed field of the User table would be set to false. But it stays true. So, what is the purpose of creating a token if the corresponding user account stays confirmed? Or in other words: What do I need to do in order to generate a new token AND also set the account to NOT confirmed?
To summarise the discussion in comments: tokens are not stored anywhere - they are crypto-generated (not exactly sure about exact process of generation) from SecruityStamp and when they are coming back, they can be de-crypted and compared.
As for EmailConfirmed field - this is for you to maintain and look after. You'll manually need to deny login for users with no confirmed email. And you'll need to set the flag when email confirmation does come through.