Open EnmanuelParedesR opened 1 year ago
One possible solution would be to call an API and retrieve the forceChangePasswordNextSignIn value and with it, this should work I guess, but I'll like to avoid making an Az Function to get something that is 'already' there.
You should be trying to read the forceChangePasswordNextLogin attribute in Get-requiresMigration-status-signin
. The attribute name will be for Azure AD Graph, not MS Graph API. Make sure to check AppInsights logs to check if it is read back properly.
You need to modify login-noninteractive
to support forceChangePasswordNextLogin
attribute being set to true
.
<TechnicalProfile Id="login-NonInteractive">
<InputClaims>
<!-- Continue if the password is expired -->
<InputClaim ClaimTypeReferenceId="continueOnPasswordExpiration" DefaultValue="true" />
</InputClaims>
<OutputClaims>
<!-- Indicates whether user needs to reset the password.
If the value of this claim is true, other claims aren't return-->
<OutputClaim ClaimTypeReferenceId="forceChangePasswordNextLogin" PartnerClaimType="passwordExpired" />
</OutputClaims>
</TechnicalProfile>
Policy looks fine otherwise. You should use policy to return forceChangePasswordNextLogin
to false
and set appropiate password policy attribute also.
Hello. This is the definition of Get-requiresMigration-status-signin
<TechnicalProfile Id="Get-requiresMigration-status-signin">
<Metadata>
<Item Key="Operation">Read</Item>
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
<Item Key="UserMessageIfClaimsPrincipalDoesNotExist">An account could not be found for the provided user ID.</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.emailAddress" Required="true" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" />
<!-- Set a default value (false) in the case the account does not have this attribute defined -->
<OutputClaim ClaimTypeReferenceId="requiresMigration" PartnerClaimType="extension_requiresMigration" DefaultValue="false" />
<OutputClaim ClaimTypeReferenceId="extension_fbaGuid"/>
<!-- <OutputClaim ClaimTypeReferenceId="forceChangePasswordNextLogin" PartnerClaimType="passwordProfile.forceChangePasswordNextLogin" DefaultValue="false" /> -->
</OutputClaims>
<IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>
Its commented because if a save it and then try to save my B2C_1A_SEAMLESSMIGRATION_SIGNUPORSIGNIN an error like is throw:
_is not supported in Azure Active Directory Provider technical profile 'Get-requiresMigration-status-signin' of policy 'B2C_1A_SeamlessMigration_signuporsignin'. If it is a claim with default value, add AlwaysUseDefaultValue="true" to the output claim mapping.Output Claim 'passwordProfile.forceChangePasswordNextLogin' is not supported in Azure Active Directory Provider technical profile 'Get-requiresMigration-status-signin' of policy 'B2C_1A_SeamlessMigrationsignuporsignin'. If it is a claim with default value, add AlwaysUseDefaultValue="true" to the output claim mapping.
My login-NonInteractive is interactive and those other profiles are in my other extension and work fine:
The problem with this (I guess) is that my login interactive is called after these triggers, because the requiresMigration flow first changes the password (if true) before calling it.
This is my complete technical profile
And, this is an example of the log. [The expected result should not call the API] this JSON is a bit confusing (even with the vs tool) I see the condition value (true) but I can find the value of the property itself, but I imaging is coming null.
[
{
"Kind": "Headers",
"Content": {
"UserJourneyRecorderEndpoint": "urn:journeyrecorder:applicationinsights",
"CorrelationId": "bef2076a-f6fd-4bf6-bb85-39d0380d520f",
"EventInstance": "Event:SELFASSERTED",
"TenantId": "{tenant}.onmicrosoft.com",
"PolicyId": "B2C_1A_SeamlessMigration_signuporsignin"
}
},
{
"Kind": "Transition",
"Content": {
"EventName": "SELFASSERTED",
"StateName": "Initial"
}
},
{
"Kind": "Predicate",
"Content": "Web.TPEngine.StateMachineHandlers.CrossSiteRequestForgeryValidationHandler"
},
{
"Kind": "HandlerResult",
"Content": {
"Result": true,
"Statebag": {
"MACHSTATE": {
"c": "2022-12-02T03:54:31.5964483Z",
"k": "MACHSTATE",
"v": "Initial",
"p": true
},
"JC": {
"c": "2022-12-02T03:54:27.7962671Z",
"k": "JC",
"v": "es",
"p": true
},
"Complex-CLMS": {
"passwordPolicies": "DisablePasswordExpiration, DisableStrongPassword"
},
"ORCH_CS": {
"c": "2022-12-02T03:54:37.7108047Z",
"k": "ORCH_CS",
"v": "1",
"p": true
},
"ORCH_IDX": {
"c": "2022-12-02T03:54:27.999391Z",
"k": "ORCH_IDX",
"v": "0",
"p": true
},
"RA": {
"c": "2022-12-02T03:54:27.999391Z",
"k": "RA",
"v": "0",
"p": true
},
"RPP": {
"c": "2022-12-02T03:54:27.780644Z",
"k": "RPP",
"v": "OAUTH2",
"p": true
},
"RPIPP": {
"c": "2022-12-02T03:54:27.780644Z",
"k": "RPIPP",
"v": "OAuth2ProtocolProvider",
"p": true
},
"OTID": {
"c": "2022-12-02T03:54:27.780644Z",
"k": "OTID",
"v": "{tenant}.onmicrosoft.com",
"p": true
},
"APPMV": {
"c": "2022-12-02T03:54:27.7962671Z",
"k": "APPMV",
"v": "V2",
"p": true
},
"IC": {
"c": "2022-12-02T03:54:27.999391Z",
"k": "IC",
"v": "True",
"p": true
},
"MSG(f795224b-205d-4877-9d71-f17539c129e5)": {
"c": "2022-12-02T03:54:27.999391Z",
"k": "MSG(f795224b-205d-4877-9d71-f17539c129e5)",
"v": "{\"TenantId\":\"{tenant}.onmicrosoft.com\",\"PolicyId\":\"B2C_1A_SeamlessMigration_signuporsignin\",\"RedirectUri\":\"https://{idp}.azurewebsites.net/signin-oidc-pswd-change\",\"AdditionalParameters\":{\"p\":\"B2C_1A_SEAMLESSMIGRATION_SIGNUPORSIGNIN\"},\"Nonce\":\"defaultNonce\",\"ClientId\":\"2aedada7-0bd8-4a3e-b274-9d22bf96f281\",\"ResponseType\":\"id_token\",\"ResponseRedirector\":{\"URI\":\"https://{idp}.azurewebsites.net/signin-oidc-pswd-change\",\"D\":false,\"WF\":true,\"R\":false},\"Scope\":\"openid\",\"AppModelVersion\":1,\"ScopedProviders\":[]}",
"p": true,
"t": "OAuth2"
},
"IMESSAGE": {
"c": "2022-12-02T03:54:27.999391Z",
"k": "IMESSAGE",
"v": "f795224b-205d-4877-9d71-f17539c129e5",
"p": true
},
"EID": {
"c": "2022-12-02T03:54:28.0150159Z",
"k": "EID",
"v": "urn:com:microsoft:aad:b2c:elements:contract:unifiedssp:2.1.5",
"p": true
},
"SE": {
"c": "2022-12-02T03:54:31.5964483Z",
"k": "SE",
"v": "Self-asserted_local",
"p": true
},
"CMESSAGE": {
"c": "2022-12-02T03:54:37.7108047Z",
"k": "CMESSAGE",
"v": "f795224b-205d-4877-9d71-f17539c129e5",
"p": true
},
"ComplexItems": "_MachineEventQ, REPRM, TCTX"
},
"PredicateResult": "True"
}
},
{
"Kind": "Predicate",
"Content": "Web.TPEngine.StateMachineHandlers.IsDisplayControlActionRequestHandler"
},
{
"Kind": "HandlerResult",
"Content": {
"Result": false,
"PredicateResult": "False"
}
},
{
"Kind": "Predicate",
"Content": "Web.TPEngine.StateMachineHandlers.IsClaimVerificationRequestHandler"
},
{
"Kind": "HandlerResult",
"Content": {
"Result": true,
"PredicateResult": "False"
}
},
{
"Kind": "Predicate",
"Content": "Web.TPEngine.StateMachineHandlers.SelfAssertedMessageValidationHandler"
},
{
"Kind": "HandlerResult",
"Content": {
"Result": false,
"RecorderRecord": {
"Values": [
{
"Key": "Validation",
"Value": {
"Values": [
{
"Key": "SubmittedBy",
"Value": null
},
{
"Key": "ProtocolProviderType",
"Value": "SelfAssertedAttributeProvider"
},
{
"Key": "TechnicalProfileEnabled",
"Value": {
"EnabledRule": "Always",
"EnabledResult": true,
"TechnicalProfile": "Get-requiresMigration-status-signin"
}
},
{
"Key": "ValidationTechnicalProfile",
"Value": {
"Values": [
{
"Key": "TechnicalProfileId",
"Value": "Get-requiresMigration-status-signin"
},
{
"Key": "MappingPartnerTypeForClaim",
"Value": {
"PartnerClaimType": "signInNames.emailAddress",
"PolicyClaimType": "signInName"
}
}
]
}
},
{
"Key": "Precondition",
"Value": {
"$id": "1",
"Type": 1,
"ExecuteActionsIf": true,
"ActionTypes": [
1
],
"Values": [
"forceChangePasswordNextLogin",
"True"
]
}
},
{
"Key": "Precondition",
"Value": {
"$id": "2",
"Type": 1,
"ExecuteActionsIf": true,
"ActionTypes": [
1
],
"Values": [
"requiresMigration",
"False"
]
}
},
{
"Key": "TechnicalProfileEnabled",
"Value": {
"EnabledRule": "Always",
"EnabledResult": true,
"TechnicalProfile": "UserMigrationViaLegacyIdp"
}
},
{
"Key": "ValidationTechnicalProfile",
"Value": {
"Values": [
{
"Key": "TechnicalProfileId",
"Value": "UserMigrationViaLegacyIdp"
},
{
"Key": "MappingPartnerTypeForClaim",
"Value": {
"PartnerClaimType": "email",
"PolicyClaimType": "signInName"
}
},
{
"Key": "MappingPartnerTypeForClaim",
"Value": {
"PartnerClaimType": "password",
"PolicyClaimType": "password"
}
}
]
}
},
{
"Key": "Exception",
"Value": {
"Kind": "Handled",
"HResult": "80131500",
"Message": "ErrorCodes: AADB2C",
"Data": {
"IsPolicySpecificError": false
}
}
}
]
}
}
]
},
"Statebag": {
"ComplexItems": "_MachineEventQ, REPRM, TCTX, S_CTP, M_EXCP"
},
"Exception": {
"Kind": "Handled",
"HResult": "80131500",
"Message": "ErrorCodes: AADB2C",
"Data": {
"IsPolicySpecificError": false
}
},
"PredicateResult": "False"
}
},
{
"Kind": "Action",
"Content": "Web.TPEngine.StateMachineHandlers.SendRetryHandler"
},
{
"Kind": "HandlerResult",
"Content": {
"Result": true
}
}
]
Hello.
I'm already using both of these policies (merged as one) and everything is good except for one scenario: if my flag "requiresMigration" is still active and if The forceChangePasswordNextLogin is also active, my policy would go and execute the requiresMigration and compare the password with the one inserted by the user (which would not be correct because we already give them an OTP password using the console). I try to read the variable but I'm not able to accomplish it.
I'm trying to ignore the API Request in this technical profile because the password to compare would be the OTP one.
I'm also trying to retrieve the passwordProfile.forceChangePasswordNextLogin but as I check is not listed in the User Profiles Attributes, so, how can I get it and ignore this execution?
Adding pictures of the scenario:
1 - The requires migration flag is on (so the login should call the API to compare with the old provider)
2 - BUT, a temporary password is given to the user:
In this case, this means the passwordProfile.forceChangePasswordNextLogin is true, but if we execute the login with the password of step 2:
If I use the password of the old IDP the screen for the password reset appears, but I want to ignore the old password if they give them a new one.
It's also good to know that if I try to upload my Signup I get this error
_Output Claim 'passwordExpired' is not supported in Azure Active Directory Provider technical profile 'Get-requiresMigration-status-signin' of policy 'B2C_1A_SeamlessMigrationsignuporsignin
I try with passwordExpired and passwordProfile.forceChangePasswordNextLogin. In my other extension this ones are retrieve but using the login-interactive.
@JasSuri Can you probably help me with this? I already implement 95% of the functionality, I just need to resolve this last one.