WSO2 removes email when creating a user via SSO - saml-2.0

we are creating users in WSO2 via multiple identity providers (mostly with ADFS backends). We are mapping the UPNs into the subject on ADFS side and expected to get user ids like user#domain on WSO2 side (using just-in-time provisioning. An example SAML response looks like this:
<Subject>
<NameID>user#domain.com</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="_d685e02e861d57cbf40c2a2af996f920" NotOnOrAfter="2018-12-04T15:32:47.404Z" Recipient="https://ourdomain.de/commonauth"/>
</SubjectConfirmation>
</Subject>
<Conditions>
<AudienceRestriction>
<Audience>ourdomain.com</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="Givenname">
<AttributeValue>adfsFirsname</AttributeValue>
</Attribute>
<Attribute Name="Lastname">
<AttributeValue>adfsLastname</AttributeValue>
</Attribute>
<Attribute Name="Role">
<AttributeValue>domain-user</AttributeValue>
<AttributeValue>admin</AttributeValue>
<AttributeValue>test</AttributeValue>
</Attribute>
<Attribute Name="username">
<AttributeValue>test</AttributeValue>
</Attribute>
<Attribute Name="mail">
<AttributeValue>user#domain.de</AttributeValue>
</Attribute>
</AttributeStatement>
</Conditions>
The problem is, that on WSO2 side we just get user as the userid and not the expected user#domain. Doesn't matter how we configure the mapping, the last #stuff gets cutted. Does anybody know, how to configure this, to get the complete user#domain as userid in WSO2?
Hope you can help me!

By default, WSO2 products will take username as #. That's why the #stuff part of the username was removed. If you want to use email as the username you need to configure. Here is the detailed documentation
Then the username will be treated as user#domain#tenentDomain. For the super tenant, you don't need to the #tenentDomain.

I actually managed to create a custom-claim-dialog on ADFS side, which manipulates the claim to contain one more #-symbol. This forces WSOIS to do what I want. Not the most beautiful solution, but it works for now...

Related

Implementing Sage Intacct API via Postman

I would like to get the invoice link from the purchase order implementing Sage Intacct API via Postman.
I suppose it can be done by following sequences(or by only one api request? not sure about this).
Order a purchase
Create a purchase receipt
Get an invoice link from it
Please refer to this API document (https://developer.intacct.com/api).
i.e. This is the body of a request to create a purchase transaction.
<?xml version="1.0" encoding="UTF-8"?>
<request>
<control>
<senderid>{{sender_id}}</senderid>
<password>{{sender_password}}</password>
<controlid>{{$timestamp}}</controlid>
<uniqueid>false</uniqueid>
<dtdversion>3.0</dtdversion>
<includewhitespace>false</includewhitespace>
</control>
<operation>
<authentication>
<sessionid>{{temp_session_id}}</sessionid>
</authentication>
<content>
<function controlid="{{$guid}}">
<create_potransaction>
<transactiontype>Purchase Requisition</transactiontype>
<datecreated>
<year>2013</year>
<month>6</month>
<day>19</day>
</datecreated>
<vendorid>1001</vendorid>
<referenceno>1234</referenceno>
<vendordocno>vendordocno001</vendordocno>
<datedue>
<year>2013</year>
<month>6</month>
<day>20</day>
</datedue>
<payto>
<contactname>Jameson Company</contactname>
</payto>
<exchratetype>Intacct Daily Rate</exchratetype>
<customfields/>
<potransitems>
<potransitem>
<itemid>75300GL</itemid>
<quantity>100</quantity>
<unit>Each</unit>
<price>1</price>
<locationid>MGMT-US</locationid>
<departmentid>IT</departmentid>
</potransitem>
</potransitems>
</create_potransaction>
</function>
</content>
</operation>
</request>
Thank you in advance.
You can download the Postman collection file (API) from the developer docs.
And then just refer to Purchasing/Purchasing Transactions/Create Transaction (Legacy).
You can change the body (SOAP) content.
I'm sure you can manage it.

Using ADB2C phone factor technical profile to validate a phone number before creating an account

I'm trying to create a custom ADB2C policy which should follow a journey such as...
User enters a phone number to verify
User receives a code to verify the number and enters this on the view
A claim is set which is used in the next step to save to AD.
I can see I need to use the phone factor technical profile as per the Microsoft docs, but I couldn't see whether this could be done before a user has signed up as it seems to want a UserID as an input claim (see Input claims required). All the samples seem to point to MFA and editing phones already associated to a user.
Is it possible to do this?
Secondly, is there any value in mixing the one-time password technical profile in this flow or is that more for just OTP code generation (not sending and accepting the inputs from the user)?
Update
So Ive managed to create the user journey which shows the UI correctly so it seems I can enter a phone number but now when I submit it I get an error "AADB2C90154: A multi-factor verification request failed to get a session id from the service."
As far as I can tell, the session technical profile is fine so not sure what the problem could be?
I also tried disabling the session but its seems like the phone tech profile needs it?
Sample technical profile
<TechnicalProfile Id="PhoneFactor-InputOrVerify">
<DisplayName>PhoneFactor</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PhoneFactorProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ContentDefinitionReferenceId">api.phonefactor</Item>
<Item Key="ManualPhoneNumberEntryAllowed">true</Item>
<Item Key="setting.authenticationMode">sms</Item>
<Item Key="setting.autodial">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="UserId" DefaultValue="TEST" />
<InputClaim ClaimTypeReferenceId="phoneNumber" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="verifiedPhone" PartnerClaimType="Verified.OfficePhone" />
<OutputClaim ClaimTypeReferenceId="newVerifiedPhone" PartnerClaimType="newPhoneNumberEntered" />
</OutputClaims>
</TechnicalProfile>
#Raj,
I don't see how you are setting the userIdForMFA other than the default value? However, the Azure documentation isn't very clear here. Try using an inputClaimsTransformation that sets the userId Value.
For example:
Add this to the MFA technical profile:
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="CreateUserIdForMFA2" />
</InputClaimsTransformations>
Add this to your claims transformation:
<ClaimsTransformation Id="CreateUserIdForMFA2" TransformationMethod="CreateStringClaim">
<InputParameters>
<InputParameter Id="value" DataType="string" Value="test12345#{YourTenant}.onmicrosoft.com"/>
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="userIdForMFA" TransformationClaimType="createdClaim" />
</OutputClaims>
</ClaimsTransformation>

Azure AD SAML2 response: System.Security.Cryptography not supporting http://www.w3.org/2001/04/xmldsig-more#rsa-sha256

everyone. I have a mystery. It may be obvious to someone, hence this.
About 10 days ago, my Service Provider app started to throw a curious error after working flawlessly for several weeks. I have a service provider running both locally and on Azure. The app uses KentorAuthServices to handle the messy XML and crypto bits. It was running smoothly and then, suddenly, it began to throw the error, "Could not create hash algorithm object." I enabled framework debugging and traced it to the very location indicated in the last line of this extract of the stack trace:
[CryptographicException: Could not create hash algorithm object.]
System.Security.Cryptography.Xml.Reference.CalculateHashValue(XmlDocument document, CanonicalXmlNodeList refList) +160912
System.Security.Cryptography.Xml.SignedXml.CheckDigestedReferences() +154
System.Security.Cryptography.Xml.SignedXml.CheckSignature(AsymmetricAlgorithm key) +73
Indeed, it cannot create the hash algorithm object because the algorithm represented by this URI
http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
now purports to be unsupported, despite having a custom handler for it built into KentoAuthServices-and which worked as expected until this sudden turn of events. Just as a sanity check, I pointed the SP app at Kentor's own stub IdP and the app behaves as expected. As well, I validated the SAML response, which I will reproduce below, against OneLogin's SAML validation utility, which also reports that the response is valid but that the algorithm is unsupported.
Things I do know:
The Azure AD cert is current, complete, and accessible in the Trusted
Root cert store of LocalMachine, and created after the October 10
policy change for rollovers (which should be irrelevant here anyway).
The SP is not signing the request with any kind of funky, self-signed
cert; nor did it ever.
Both locally and on Azure, the app is pegged to
an SSL port.
The configuration of the app--EntityId, Issuer, metadata
location and loading, binding, request signing behavior; and so
on--has remained unchanged--except for my testing, which added a swappable IdP reference pointed to the stub provider.
Azure AD successfully processes the request and
issues a response, which is otherwise valid; however,
System.Security.Cryptography cannot create the hash for the
signature.
I feel like I'm missing something obvious, except for the fact that the app was unchanged from one day to the next; hence, I'm obliged to ask if anything in the world has changed to explain why rsa-sha256 is coming up dead. Here's the redacted SAML request and response for your perusal. Most identifying info is removed, but you already know it's from Azure AD so the cert is present and you can validate it for your edification. Thanks, and have a great day.
<saml2p:AuthnRequest
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
ID="id1cf99748a239485692824ff1b950b5f9"
Version="2.0"
IssueInstant="2016-11-29T16:44:34Z"
Destination="https://login.windows.net:443/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx/saml2"
AssertionConsumerServiceURL="https://xxxx.azurewebsites.net/AuthServices/Acs">
<saml2:Issuer>https://xxxxx.xxx/federation</saml2:Issuer>
</saml2p:AuthnRequest>
<samlp:Response
ID="_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Version="2.0"
IssueInstant="2016-11-29T16:44:36.521Z"
Destination="https://xxxxxxxx.azurewebsites.net/AuthServices/Acs"
InResponseTo="id1cf99748a239485692824ff1b950b5f9"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer
xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/
</Issuer>
<samlp:Status>
<samlp:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<Assertion
ID="_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx"
IssueInstant="2016-11-29T16:44:36.505Z"
Version="2.0"
xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<Issuer>https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx/</Issuer>
<ds:Signature
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod
Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference
URI="#_2a5aa895-bcf1-4f98-87d6-187e7d75338c">
<ds:Transforms>
<ds:Transform
Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod
Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:DigestValue>
HE62WvhO505xxxxxxxxnopQTPfL6LybGYySKUKfBxtY=
</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>E8bvvT1iw148RaVOtlPWWMhPMq121arxJ2lwRd3Boi5Xe3Lw+sc9TgCWsmFa4tcIq0idmYTkYVio4cBDNnzIcMqy28JeeiF53nriO3eyxRQiPeJhyy6JUFnbhWEa6DcYvIbD14izrvdQGuGzULeL8K2cc32xDnCjYZXAWvY4V+iaEJhXqc50bfplUXwTcgo2YzPckmh/+iad0jVFBBj1S7bMDp9+hOvUHgrwU/FIm8H7Y/g6rZZ2mlkEsdRP0WRQfCgI/IHLf1IqUdaGE9hZpqcecmtAiKytWIe/0z/8zzUC3Xp2f+L2XEXMH3Y7iNOyKr38X3FQ/
OChWEdYLIj3rw==
</ds:SignatureValue>
<KeyInfo
xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>MIIC8DCCAdigAwIBAgIQNJKIhylW6qVJDAuPDpyGfDANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQDEylNaWNyb3NvZnQgQXp1cmUgRmVkZXJhdGVkIFNTTyBDZXJ0aWZpY2F0ZTAeFw0xNjExMjQxNDI2NTlaFw0xNzExMjQxNDI2NTlaMDQxMjAwBgNVBAMTKU1pY3Jvc29mdCBBenVyZSBGZWRlcmF0ZWQgU1NPIENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApMAryO4ZkQ5WE+2QOK1oe8cXa00JH4zGDjRF92Nj4s8NrPF+2zR2IwTYV3yH5kTckCYU2+i+jDr4lBRvjG+LSoN9xdUtu4pF9Ya1v6VN6ELWnTtZYSMY7Xh3ztjF7jmWFSEvANTcTLq5wSfbZuDfti6zdJ+TP6DSN6Q3cR0wqdPJbR4NlQdpmIVAIHrpur218IhRSMcodxlKdS47cU7jTb1Vqo9uzRmrz9l5aZnPgxzv2OKHafD7E/eDIUMjkfOoZbNJJIfBy1wrGUHBLdb318VVIMDtym4Xw52TuFJ1O0dWRZU4pGGh8Vo81Hz689i8cTYv0v4bUmUeCE9kHOTHbQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAuoJMRWb3hj0f7Bg8jFTRizA+3sVXI98MKRCmxDHy84LQi5VE8VOW9TXXN8cfPQ0MlFOGg5aeePWMjr4Pmwfq5Q1aZ0JsQszAIhKzIq1jGadwlkAs1VKA37oHa6aa8OrAtLYhA5xwqq5q6oE1AULuC7g697FoSO0Q8MpHl6VCxvuqXzHQ/KYXiJ6hqpHTZN8eliBwio7+xP0O23QdM0sgkO5EvdSiuB5s23e77iutJD8YvD+oOz3QVf9OeOuocK1TtQmFaiI3kkliM1sfWowHjfIOiPjNpSBmEuKiq02XCWTDzkuYCxcRdgVnhRG+/SRqv+OTJIs6vnAWrtsFIbRGt</X509Certificate>
</X509Data>
</KeyInfo>
</ds:Signature>
<Subject>
<NameID
Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">xxxxxxxxx.xxxxxxxxxxxxxxx#Xxxxxxxxxxx.com
</NameID>
<SubjectConfirmation
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData
InResponseTo="id1cf99748a239485692824ff1b950b5f9"
NotOnOrAfter="2016-11-29T16:49:36.505Z"
Recipient="https://xxxxxxxxxxxxxxxxxxxxxxx.azurewebsites.net/AuthServices/Acs"/>
</SubjectConfirmation>
</Subject>
<Conditions
NotBefore="2016-11-29T16:39:36.505Z"
NotOnOrAfter="2016-11-29T17:39:36.505Z">
<AudienceRestriction>
<Audience>https://xxxxxxxxxxxxxx.com/federation</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute
Name="http://schemas.microsoft.com/identity/claims/tenantid">
<AttributeValue>ccbf68cb-7932-44bd-b015-cb686e0a4441</AttributeValue>
</Attribute>
<Attribute
Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
<AttributeValue>94d0114a-c4b8-4568-bf63-4b597aa65eda</AttributeValue>
</Attribute>
<Attribute
Name="http://schemas.microsoft.com/identity/claims/displayname">
<AttributeValue>xxxxxxxxxxxxxxxxxxxx</AttributeValue>
</Attribute>
<Attribute
Name="http://schemas.microsoft.com/identity/claims/identityprovider">
<AttributeValue>live.com</AttributeValue>
</Attribute>
<Attribute
Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
<AttributeValue>xxxxxxxxxxxxx</AttributeValue>
</Attribute>
<Attribute
Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
<AttributeValue>xxxxxxxxxxxxxxxxxxxxxxx</AttributeValue>
</Attribute>
<Attribute
Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
<AttributeValue>xxxxxxxxxxxxxxxxxxxxx#Xxxxxxxxxxxxxxxxxx.com</AttributeValue>
</Attribute>
<Attribute
Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
<AttributeValue>xxxxxxxxxxxxxxxx.xxxxxxxxxxxx#xxxxxxxxxxxxxxxxxxxx.com</AttributeValue>
</Attribute>
</AttributeStatement>
<AuthnStatement
AuthnInstant="2016-11-27T02:37:17.000Z"
SessionIndex="_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx">
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
</samlp:Response>

DNN friendly URL module is not able to rewrite the url correctly

In DNN 8, I have 3 (three) different portals, all with the same IA (pages & content). Example: portal1.site.com, portal2.site.com, portal3.site.com.
Using SiteUrl.config, I want to re-write the URL so that a vanity URL that doesn't exist redirects to the correct page. After further investigation, I realized that siteurl.config uses URLs in relative basis. It's not able to comprehend what portal you're coming from.
<RewriterRule>
<LookFor>[^?]*/plan/speakers/.*-(.*)</LookFor>
<SendTo>~/Default.aspx?TabId=180&SpeakerId=$1</SendTo>
</RewriterRule>
<RewriterRule>
<LookFor>[^?]*/plan/speakers/.*-(.*)</LookFor>
<SendTo>~/Default.aspx?TabId=144&SpeakerId=$1</SendTo>
</RewriterRule>
<RewriterRule>
<LookFor>[^?]*/plan/speakers/.*-(.*)</LookFor>
<SendTo>~/Default.aspx?TabId=264&SpeakerId=$1</SendTo>
</RewriterRule>
If a user wants to go to portal1.site.com/plan/speakers/mike, portal2.site.com/plan/speakers/mike, or portal3.site.com/plan/speakers/mike, they all redirect to tabid 180 (which works only for the second portal).
I was able to implement a workaround.
1. you want to mask a new url using IIS rewrite in the web.config.
<rule name="Redirect to plan" enabled="true" stopProcessing="true">
<match url="^plan/speakers/([_0-9a-z-]+)-([0-9]+)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{HTTP_HOST}" pattern="^(.*).domain.*" />
</conditions>
<action type="Rewrite" url="/{C:1}/{R:0}" />
</rule>
This will re-write your url to something like this: portal1/plans, portal2/plans, etc.
Then, you want to edit your siteurl.config to account for these re-writes.
<RewriterRule>
<LookFor>[^?]*/portal1/plan/speakers/.*-(.*)</LookFor>
<SendTo>~/Default.aspx?TabId=180&SpeakerId=$1</SendTo>
</RewriterRule>
<RewriterRule>
<LookFor>[^?]*/portal2/plan/speakers/.*-(.*)</LookFor>
<SendTo>~/Default.aspx?TabId=144&SpeakerId=$1</SendTo>
</RewriterRule>
<RewriterRule>
<LookFor>[^?]*/portal3/plan/speakers/.*-(.*)</LookFor>
<SendTo>~/Default.aspx?TabId=264&SpeakerId=$1</SendTo>
</RewriterRule>
P.S. Make sure too add these urls to the list of to-ignore in your advanced url settings.
I would have done this by adding Records to the TabURLS table for each page. If you modify a Page, using the page settings, you can modify the URL of the page. Try that. Look at the records in the table for that page.
select * from taburls where tabid = ##
Then change the URL back to the original URL
select * from taburls where tabid = ##
See if it adds a new record there. If so, then just copy the format of that "row" in the table for any additional records you need to create.
You might also check out this codeplex project

Spring Security 3.1 ActiveDirectoryLdapAuthenticationProvider returning partial result exception

I am trying to authenticate users to an Active Directory Instance using spring security, I am getting an Partial Results Exception. I am going around in circles trying to figure this out. Below is my config.
security-app-context
<authentication-manager erase-credentials="true">
<authentication-provider>
<user-service>
<user name="admin#damien.com" authorities="ROLE_ADMINISTRATOR" password="123admin123" />
</user-service>
</authentication-provider>
<authentication-provider ref="ldapActiveDirectoryAuthProvider"/>
</authentication-manager>
<bean id="ldapActiveDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="myDomain.com" />
<constructor-arg value="ldap://ldapurl:389/" />
<property name="convertSubErrorCodesToExceptions" value="true"/>
</bean>
Error I am getting
org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 0 org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntryInternal(SpringSecurityLdapTemplate.java:239)
I am struggling to find examples and the documentation indicates I am working in the right direction.
This is from the logs
SpringSecurityLdapTemplate.java 213 - Searching for entry under DN '', base = 'dc=myDomain,dc=com', filter = '(&(objectClass=user)(userPrincipalName={0}))'
and this is what I would expect that to look like on a successful attempt from some scripts that work
Searching for entry under DN 'OU=Users and Groups,DC=one,DC=two,DC=myDomain,DC=com', base = 'OU=Users and Groups,DC=one,DC=two,DC=myDomain,DC=com', filter = '(&(objectClass=user)(userPrincipalName={0}))'
Do I need to get the DN populated? How? I have looked through the ActiveDirectoryLdapAuthenticationProvider properties and don't see a way? Also the base is off but myDomain.com is the correct domain for users e.g john.doe#myDomain.com. Has anyone come across a similar problem?
To solve this I used the default LDAP provider which enables user search base to be specified, specifying the user search base and user search filter.
<ldap-authentication-provider
user-search-base="OU=Users and Groups,DC=abc,DC=myDomain,DC=com"
user-search-filter="userPrincipalName={0}" />
A user would then be logging in with john.doe#myDomain.com but the usersearch base is more specific(abc.myDomain.com). I believe AD Spring was falling down due to this.

Resources