I have an application that authenticates directly against a WIF/WCF active STS. The application is also a passive STS, acting as a WS-Federation endpoint for website relying parties.
When a user logs into a website RP, they're redirected to the passive STS for authentication (username and password) and in a two-step process, the passive STS (acting as an active RP) sends an Issue RST to the STS, and receives a signed SAML token in return. For the second step, the passive STS sends a second Issue RST to the STS, authenticating with the token in received in the previous step.
The problem is that during the second step, the WCF client strips the <Signature> element from the SAML assertion before sending it back to the STS in the SOAP header. I've verified (by test-serializing the token passed to ChannelFactory<TChannel>.CreateChannelWithIssuedToken) that the token still has the signature present when I call IWSTrustContract.Issue on the generated channel.
This is the assertion XML as it should be provided to the STS:
<saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="_0a5efbe5-446c-459c-8aaa-dda87748bca2" Issuer="https://sts.environment.com/" IssueInstant="2014-01-30T21:48:56.673Z" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<saml:Conditions NotBefore="2014-01-30T21:48:56.673Z" NotOnOrAfter="2014-01-30T22:48:56.673Z">
<saml:AudienceRestrictionCondition>
<saml:Audience>https://login.environment.com/</saml:Audience>
</saml:AudienceRestrictionCondition>
</saml:Conditions>
<saml:AttributeStatement>
<saml:Subject>
<saml:SubjectConfirmation>
<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:holder-of-key</saml:ConfirmationMethod>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<trust:BinarySecret xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512"><!--Removed--></trust:BinarySecret>
</KeyInfo>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Attribute AttributeName="upn" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml:AttributeValue><!--Removed--></saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#_0a5efbe5-446c-459c-8aaa-dda87748bca2">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue><!--Removed--></DigestValue>
</Reference>
</SignedInfo>
<SignatureValue><!--Removed--></SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate><!--Removed--></X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</saml:Assertion>
And this is what the STS receives, per the Service Trace Viewer:
<saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="_0a5efbe5-446c-459c-8aaa-dda87748bca2" Issuer="https://sts.environment.com/" IssueInstant="2014-01-30T21:50:27.842Z" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<saml:Conditions NotBefore="2014-01-30T21:50:27.841Z" NotOnOrAfter="2014-01-30T22:50:27.841Z">
<saml:AudienceRestrictionCondition>
<saml:Audience>https://login.environment.com/</saml:Audience>
</saml:AudienceRestrictionCondition>
</saml:Conditions>
<saml:AttributeStatement>
<saml:Subject>
<saml:SubjectConfirmation>
<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:holder-of-key</saml:ConfirmationMethod>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<trust:BinarySecret xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512"><!--Removed--></trust:BinarySecret>
</KeyInfo>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Attribute AttributeName="upn" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml:AttributeValue><!--Removed--></saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
Of course, the STS can't validate the signature of the assertion because it's been stripped, and it can't authenticate the client and issue the bearer token for the website RP.
Why is the WCF federated client stripping the signature from the assertion, and how can I make it not do that?
Related
I am using Sustainsys package Sustainsys.Saml2.AspNetCore2 to build a service provider web app in ASP.NET Core 3.1, which uses Azure B2C as the identity provider using SAML2. I have the following issue:
If I use Sha1 as the signing algorithm, using the option MinIncomingSigningAlgorithm, then an exception is thrown by CryptoConfig.CreateFromName because that method does not know the Sha1 algorithm.
If I use Sha256 as the signing algorithm then Azure B2C signs the response with Sha1 even though I have specified <Item Key="XmlSignatureAlgorithm">Sha256</Item> in the RelyingParty of my custom policy. I should note that this seems to only happen when the service provider starts the single logout flow. The login flow completes without issues and there the signing algorithm is Sha256. Here is my RelyingParty section:
<RelyingParty>
<DefaultUserJourney ReferenceId="SignUpOrSignIn" />
<TechnicalProfile Id="PolicyProfile">
<DisplayName>PolicyProfile</DisplayName>
<Protocol Name="SAML2"/>
<Metadata>
<Item Key="XmlSignatureAlgorithm">Sha256</Item>
</Metadata>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="givenName" />
</OutputClaims>
<SubjectNamingInfo ClaimType="objectId" ExcludeAsClaim="true"/>
</TechnicalProfile>
</RelyingParty>
Furthermore, the metadata of Azure B2C uses Sha256 as the signature and digest method. Here is the relevant section:
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="...">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="saml samlp xenc xs"/>
</Transform>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
</Reference>
</SignedInfo>
Any help is highly appreciated. Thank you.
It turns out that I needed to add <Item Key="XmlSignatureAlgorithm">Sha256</Item> to the tehcnical profile as well (in addition to it being part of RelyingParty as shown above). This solves the issue that I had with single logout.
<TechnicalProfile Id="Saml2AssertionIssuer">
<Protocol Name="None"/>
<OutputTokenFormat>SAML2</OutputTokenFormat>
<Metadata>
<Item Key="XmlSignatureAlgorithm">Sha256</Item>
</Metadata>
</TechnicalProfile>
Our app lies on SAML SSO 2.0 for login. We just got this error in the saml response status from the IdP and I'm not sure what this actually means and what needs to be done in order to get it fixed.
The Identity Provider our clients are using is Ping Federate and we have already configured SSO settings successfully between their IdP and our app long before.
No issue so far and now suddenly we're getting this Authentication Failed error out of nowhere while the user tries to login.
Can some one clarify what this actually means?
There hasn't been any change on the app (Service Provider) side on the SSO recently so does this mean the issue is on the IdP end?
Let me know. Thanks.
Here's the saml response (signature & client identifers changed)
<samlp:Response Version="2.0" ID="hbj8oC64PBip6qPoM9jrpS1OCfI" IssueInstant="2018-08-28T15:16:43.824Z" InResponseTo="_9a55c2b67dcd76cee19828ff496206a61b4c51237c" Destination="https://exampleapp.com/saml/login/callback"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">foobar</saml: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="#hbj8oC64PBip6qPoM9jrpS1OCfI">
<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/xmlenc#sha256"/>
<ds:DigestValue>rVffko3J5H6izfHOi4m0r4vtLHVLKbZqX6VmhYW7wIw=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
CuLJsdfsdfxc9C81bcFYtahXu98eS2izTwXUp7Hi592Qh5/b/bNgyaDjV1l3r0R4dcx+wP6IDPnqIxpk7h BezfbD8bqm1cBC3AFgLh0b9RByGto2qpxJv1HP1sMkAk03x6JPq7ec6fAFJdrkeKMq5dyl8eodjy lNu0Ql3qY3k1gIerTToQZULkAZp8WLIekPpaOKzvXotzZx3dLoprn/XA+BKZZgR8WP7jZ4t/3jJF YF1l2WjaSWOJgoz8PIjwPJZ7mvqjvYbY3u726vra3x+c0wzp+qlNZNbUzqg2CQ07RICMgHbnLKMA /PiF81helnjOCOdOTIrFmkxoiwvYz3Th6/1sLA==
</ds:SignatureValue>
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:AuthnFailed"/>
</samlp:StatusCode>
<samlp:StatusMessage>Authentication Failed</samlp:StatusMessage>
<samlp:StatusDetail>
<Cause>org.sourceid.websso.profiles.idp.FailedAuthnSsoException</Cause>
</samlp:StatusDetail>
</samlp:Status>
</samlp:Response>
Yes, the issue is on the IDP end: it was not able to authenticate the user for some reason. The logs at the IDP side should tell you (or: them) more.
I'm trying to add WS-Security to an existing service I have, where said service is accessed over TLS, and I've mostly succeeded in testing it with SoapUI.
However I'm having a problem with the response coming back; even though the response looks complete, SoapUI reports:
ERROR:org.apache.ws.security.WSSecurityException: An invalid security token was provided (Bad TokenType "")
org.apache.ws.security.WSSecurityException: An invalid security token was provided (Bad TokenType "")
at org.apache.ws.security.str.BSPEnforcer.checkEncryptedKeyBSPCompliance(BSPEnforcer.java:113)
at org.apache.ws.security.str.SecurityTokenRefSTRParser.processPreviousResult(SecurityTokenRefSTRParser.java:313)
at org.apache.ws.security.str.SecurityTokenRefSTRParser.parseSecurityTokenReference(SecurityTokenRefSTRParser.java:101)
at org.apache.ws.security.processor.ReferenceListProcessor.decryptDataRefEmbedded(ReferenceListProcessor.java:169)
at org.apache.ws.security.processor.ReferenceListProcessor.handleReferenceList(ReferenceListProcessor.java:104)
at org.apache.ws.security.processor.ReferenceListProcessor.handleToken(ReferenceListProcessor.java:64)
at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:402)
From what I'm reading, this is due to a missing TokenType attribute on the SecurityTokenReference element in the reply, and this is a condition of complying with the Basic Security Profile.
The question is - how do I get this attribute populated in WCF? I've not found any clear information on this.
The encrypted key section in the SOAP response from the WCF service looks like this:
<e:EncryptedKey Id="_0" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns="http://www.w3.org/2000/09/xmldsig#"/>
</e:EncryptionMethod>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">K6Ag94AG3hQuQ+rqQcBvb88Vl+Y=</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>FQ58hAfisez2D8J9A49xFRQjfTSFhrWP9wJDnWq0MctAyLhoAynzu3/Z0jYK91uE4DVCgkFo9QGH6O/kR1icQxkpv/xb5gcB1mJTbIpbCOzw6ZtMEfbY0r9ML2fDcChGFPM/nh70Daqi4P9IO8dIZ5EAUcERvDMFvj4fhwwVycSNFUX40/8ywQALQksPb+1j2B3pzHntcyb6CJ0qD10xjbyyQoT0BgR/HeDQEJDQNvx41eqoDSy2/ImkNNfFCXQ47/k1sN48tWur6GEzDuwUBbiAJxVrCgzc6a7F9CrhWiE6DAublBzM8/EBKP5UD5p2WTcjDQxI4cBhqRwIGYcfhQ==</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>
My WCF bindings look like this:
<customBinding>
<binding name="NewBinding0">
<security
authenticationMode="MutualCertificate"
allowSerializedSigningTokenOnReply="true"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
securityHeaderLayout="Lax"
requireSignatureConfirmation="false"
messageProtectionOrder="EncryptBeforeSign"
includeTimestamp="false"
>
<localServiceSettings detectReplays="false" />
</security>
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport />
</binding>
</customBinding>
As an afterthought, is BSP strictly required to be a "good" message? I can't see any way to switch BSP checking off in SoapUI, but given WCF doesn't apply it I assume it is acceptable? Ultimately, consumers of the service may be Java, may be .NET, may be something else, so I'm happy to drop BSP support in the name of wider compatibility if BSP can be disabled. If this does seem an acceptable path, then rather than .NET attempting to conform to BSP, how do I switch BSP processing off in SoapUI for testing? (That said, if enabling BSP in .NET is straight forward by tweaking the binding, I'm happy to persue that).
I need some guidance on my SSO implementation.
I have done couple of SAML2 implementations with success but there is something missing on this one :-O I believe it is minor but I am not sure what I am missing and I not seeing much information in the logs on the agent side :-/
So :
IDP Initiated
I am the SP Using OpenAm 10
Using J2EE Agent
Same configuration works on prod as well for other clients
SAML 2 implementation
The cross domain is enable
Certificate is loaded in the client IDP Metadata on my side
The issue is when I get the Response from the Vendor, they get redirected by the CDCSERVLET to the Login Page of OpenAm .. I am not getting why they are not authenticated.
Here the response:
<Response ID="_FAD290A87DB14BC4A8A8F435DEBDEBB3" Version="2.0" IssueInstant="2015-12-31T20:59:34.1012911Z" Destination="https://sso.com:443/sp/Consumer/metaAlias/xxx-test/sp" xmlns="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">xxx</Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#_FAD290A87DB14BC4A8A8F435DEBDEBB3">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>HPTUTyPjegeyjDW5lmMb8ggbwas=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>4Ek0xpDPj5Q==</SignatureValue>
</Signature>
<Status>
<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</Status>
<Assertion Version="2.0" ID="_BCA1E13E205E4CDCB7AB903E90606DBD" IssueInstant="2015-12-31T20:59:34.1012911Z" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<Issuer>xxx</Issuer>
<Subject>
<NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified">100</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData NotOnOrAfter="2015-12-31T21:04:34.1948917Z" Recipient="https://sso.com:443/sp/Consumer/metaAlias/xxx-test/sp"/>
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2015-12-31T20:54:34.1012911Z" NotOnOrAfter="2015-12-31T21:04:34.1012911Z">
<AudienceRestriction>
<Audience>xxx-test:saml2</Audience>
</AudienceRestriction>
</Conditions>
<AuthnStatement AuthnInstant="2015-12-31T20:59:34.1012911Z">
<SubjectLocality Address="000.0.0.000"/>
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
<AttributeStatement>
<Attribute Name="AIN">
<AttributeValue xsi:type="xsd:string">100</AttributeValue>
</Attribute>
</AttributeStatement>
</Assertion>
What I noted in that assertion is :
There is no certificate in the Signature (All my client have the
in the signature with the certificate)
On my side for the SP, I made sure that:
The Authentication Context is set to Password to match the assertion
I Disable the Federation if the NameId is Unspecified and I use the NameId as UserId
All of that should be good on my side, and I do not understand why the client gets redirected to the login page of OpenAM
Any help would be awesome !!
Thanks !
EDIT :
So, I had the vendor modified the assertion to send the <NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">xxxx</NameID>
And I added a user to the realm, and use it as transient user in my SP configuration but it resulted in the same issue !!
When the nameid-format was set as unspecified, I created that 100 user in the realm as a subject but it still did not work :-/
EDIT 3 : Here some information on the Session:
<SessionNotification vers="1.0" notid="117627">
<Session sid="AQIC5wM2LY4SfcxfxdL6szA_aGlQEkFtHROifZHX_VpqHag.*AAJTSQACMDIAAlNLABM3OTI1OTk2NjE0MDA1MjA2MTcw*" stype="user" cid="id=user-test,ou=user,dc=openam,dc=forgerock,dc=org" cdomain="dc=openam,dc=forgerock,dc=org" maxtime="60" maxidle="30" maxcaching="5" timeidle="1800" timeleft="1529" state="destroyed">
<Property name="CharSet" value="UTF-8"></Property>
<Property name="UserId" value="user-test"></Property>
<Property name="FullLoginURL" value="/sp/UI/Login?ForceAuthn=false&MinorVersion=0&RequestID=see601a9040131cc9c9d09947cf1addab3e4df292&refererservlet=https%3A%2F%2Fs-----6ForceAuthn%3Dfalse%26ProviderID%3Dhttps%253A%252F%252Fstagingcng.inspirus365.com%253A443%252F%253FRealm%253D%25252F%26MinorVersion%3D0%26Federate%3Dfalse%26IssueInstant%3D2016-01-12T21%253A30%253A22Z%26MajorVersion%3D1&IssueInstant=2016-01-12T21%3A30%3A22Z&MajorVersion=1"></Property>
<Property name="successURL" value="/sp/console"></Property>
<Property name="cookieSupport" value="true"></Property>
<Property name="AuthLevel" value="0"></Property>
<Property name="SessionHandle" value="shandle:AQIC5wM2LY4SfcwZfnMFJVMF0olMGhmq-Nmqw_BMxoVv4AA.*AAJTSQACMDIAAlNLABM3OTI1OTk2NjE0MDA1MjA2MTcw*"></Property>
<Property name="UserToken" value="user-test"></Property>
<Property name="loginURL" value="/sp/UI/Login"></Property>
<Property name="Principals" value="user-test"></Property>
<Property name="Service" value="ldapService"></Property>
<Property name="sun.am.UniversalIdentifier" value="id=user-test,ou=user,dc=openam,dc=forgerock,dc=org"></Property>
<Property name="amlbcookie" value="01"></Property>
<Property name="Organization" value="dc=openam,dc=forgerock,dc=org"></Property>
<Property name="Locale" value="en_US"></Property>
<Property name="HostName" value="205."></Property>
<Property name="AuthType" value="DataStore"></Property>
<Property name="Host" value="205."></Property>
<Property name="UserProfile" value="Ignore"></Property>
<Property name="clientType" value="genericHTML"></Property>
<Property name="AMCtxId" value="a0749ff708bff14202"></Property>
<Property name="SessionTimedOut" value="1452636294"></Property>
<Property name="authInstant" value="2016-01-12T21:30:33Z"></Property>
<Property name="Principal" value="id=user-test,ou=user,dc=openam,dc=forgerock,dc=org"></Property>
</Session>
The thing that struck me is the <Property name="AuthType" value="DataStore"></Property> (I have Federation from other vendors :0)
I am sure that the issue is because the user cannot get authenticated against OpenAM.
I am assuming that autofederation is turned off on the Service Provider side (OpenAM) and that you are using the NameID as the User ID.
After receiving the assertion the SP Account Mapper will try to find a user with that User ID in the Data Store for the Realm where the SP is defined. You can find which LDAP attribute is mapped to the User ID by going to Access Control > YOUR REALM > Data Stores > YOUR DATASTORE. Look for a property called "LDAP Users Search Attribute".
In this particular case the NameID value is "100", thus, the Account Mapper will try to find a user in your datastore with that User Id. For example, if your "LDAP Users Search Attribute" is set to "uid", the Account Mapper will try to find a user in your Directory whose "uid" is equal to "100".
So my assumption is that the Account Mapper is not able to map the incoming assertion to a valid user and it's taking you to the OpenAM's Login Page.
Hope this helps.
I figured it out ... Turned out everything was set up right but our partner was posting the Assertion to the Relay/Target URL and not the Consumer URL .....
I am currently implementing in-app purchases in an app that I am working for Windows 8.
After reading the documentation:
Request the license Information for the app:
msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.store.licenseinformation.aspx
This tells you if the app is trial or not, and the list of products bought using in-app.
To perform a purchase you need to use the objects:
CurrentApp: In live environment. This will only work when the app is APPROVED in the store, so you need to make this change before packaging to submit to the store.
CurrentAppSimulator: Debug and testing.
2.a. If you are running an app in trial mode, you purchase the app calling:
CurrentApp.RequestAppPurchaseAsync (true)
The parameter is requesting to get a string that contains XML that represents all receipts for the app and any in-app purchases. If includeReceipt is set to false, this string is empty.
2.b. Validate a purchase from your servers. Reference
We want to verify that the receipt that we got from server 2.a is genuine. To verify a receipt's authenticity, you can check the receipt's signature using the public certificate. To get this certificate, use the following URL:
go.microsoft.com/fwlink/?LinkId=246509&cid= where is the CertificateId of the receipt.
This is a real Receipt from the CurrentAppSimulator:
<?xml version="1.0" encoding="utf-8"?>
<Receipt Version="1.0" ReceiptDate="2012-08-23T14:21:40Z" CertificateId="" ReceiptDeviceId="9d6b1f28-cab8-421f-8f8d-23df2dc3abbe">
<ProductReceipt Id="d9437a12-4f91-4ef0-b0bf-527ab9da2ec9" AppId="Zolmo.JamiesRecipes_40cj6885yhw56" ProductId="JMPK_0004" PurchaseDate="2012-08-23T14:21:40Z" ProductType="Durable" />
</Receipt>
No CertificateId, how could I implement the server side validation? how can I test all this without having an app in the Store?
Thanks,
Pedro
There is no sandbox environment to do this kind of end-to-end testing for the Windows Store. This should help get you a bit further though:
The CertificateId being used by the Store currently is b809e47cd0110a4db043b3f73e83acd917fe1336 (this can change over time so your code should get this programmatically from the signed receipts)
The cert download URL becomes this:
https://go.microsoft.com/fwlink/?LinkId=246509&cid=b809e47cd0110a4db043b3f73e83acd917fe1336
Here's a sample receipt you can test your code that parses the CertificateId value to use in the URL above and for the code that verifies the signature is valid using the cert returned by the URL above:
<Receipt Version="1.0" ReceiptDate="2012-08-28T22:11:33Z" CertificateId="b809e47cd0110a4db043b3f73e83acd917fe1336" ReceiptDeviceId="4e362949-acc3-fe3a-e71b-89893eb4f528">
<AppReceipt Id="8ffa256d-eca8-712a-7cf8-cbf5522df24b" AppId="55428GreenlakeApps.CurrentAppSimulatorEventTest_z7q3q7z11crfr" PurchaseDate="2012-06-04T23:07:24Z" LicenseType="Full" />
<ProductReceipt Id="2559fa9a-9f86-0525-e655-536a6c96fac6" ProductId="Product1" PurchaseDate="2012-06-04T23:07:50Z" ExpirationDate="2012-06-07T23:07:49Z" ProductType="Durable" AppId="55428GreenlakeApps.CurrentAppSimulatorEventTest_z7q3q7z11crfr" />
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>npmBq7pdtq9FkfILSsHuVyD+QWiZg6J/klBKsyWhrw8=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>LKZSHmk6XjLaEHoJPFBB1GxVsFf2eilOXeyf2RvYtVvqjU4EIdOUfNM46sVifq3MyeE4N2s77iJmvdzgxmOM9tCimebiL7jsdpWakO0A9daImHESMPIrwZNham6jPCWaBUEOFT6PNy1v5MS+cdX25Wenk702L0wVQ6R8oGPlk5Im6Q62K69cvAFA3q/kiLHOyTZWHoIGw5lvFvAYI/aZhVoFQLv1FjK0Syg5nbMA19UrzwZ39jnJjcfuw/VX51uSv5Ze2x36HDXTpiw8wHoTzauGYzt9MXd4+qbiJ4AQys22AgO+cfAbDrTuH5duZ6DMeuFeEv8nu2p9PiVyBEOlZw==</SignatureValue>
</Signature>