Create SAML SLO request - c#

As a service provider (SP), i'm trying to create request for SLO using the URL redirect flow. After going through a lot of articles, this is what i came up with:
Create a logout request xml and digitally sign it
Convert the request xml to base64 url encoded string
Append the base64 encoded request xml to the SLO url as a querystring
Redirect page to the above constructed url (IDP)
IDP will then perform necessary SLO steps for all SPs at its end and
redirect back to our current application (which initiated the SLO
request)
Parse above response and show message in UI accordingly
However, when i got into the actual implementation, i'm faced with the following challenges, some of them not specific to SAML SLO.
To digitally sign the logout request xml, is it mandatory to
load/import the x509 certificate from .pfx file or can i use any
certificate from the certificate store which has private key?
For demo purpose, I've successfully signed the request using a certificate in my local system which has private key. This process appends the signature and pulic key information in the logout request xml.
I've encoded (Base64Url) the request xml but the resulting string length is too long (more than 4k chars), which would exceed the maximum length allowed in URL/GET request. Have i got this step wrong?
None of the articles/SAML spec mentions how the querystring should look like. Is the querystring parameter name defined by the SAML spec (which i could have missed) or is it dependent on the IDP?
All in all, i feel that SAML spec lacks articles with proper implementation which is making it extremely difficult to get the hang of it.
Note: I didn't include any of the codes i've written so far since my questions can be answered without them. However, if required, i can include them.
Few of the many referenced articles:
SSO, SAML and SLO
SAML Logout Request (SP -> IdP)
Sign XmlDocument with X509Certificate2 and Verify in C#

I would strongly suggest using an existing SAML library instead of rolling your own.
Some of these are free and you can examine the source code to see how to do it.
Or alternatively just use the stack itself!

Related

Google Drive v3 API file - 403 when specifying alt=media

This C# code, with a proper access token (for scope drive.readonly) in the Authorization header, will work fine and return the file metadata in json format
_httpClient.GetAsync($"https://content.googleapis.com/drive/v3/files/{someDriveFileId}")
However this code (still with the same access token) will return a 403 :
_httpClient.GetAsync($"https://content.googleapis.com/drive/v3/files/{someDriveFileId}?alt=media")
And the following response html (exactly as returned) :
<html><title>Error 403 (Forbidden)!!1</title><a
href=//www.google.com/><span id=logo
aria-label=Google></span></a><p><b>403 Forbidden</b><p>Your client
does not have permission.\n
I've been using this code in production for years and it worked fine, so i suppose it's related to the recent changes at Google regarding the OAuth screens ?
I'm not sure what i should change here, or what i'm doing (now) wrong. Also the message seems a little sketchy for something made at Google, makes me think there is maybe an issue on their side ?
UPDATE:
Thanks to #Iamblichus for fixing the layout of my original answer. I'm newer to stackoverflow posting.
Even though the change in the original answer appears to be at the root of the problem, I found it difficult to use the troubleshooting steps to come to a working solution. I also was already passing the Authorization Bearer token solution, and that was not fixing my problem. After some trial and error the change I had to make was:
Broken GET URL:
https://content.googleapis.com/drive/v2/files/MY_FILE_ID?key=MY_KEY&alt=media&source=downloadUrl
Working GET URL:
https://www.googleapis.com/drive/v2/files/MY_FILE_ID?alt=media&source=downloadUrl
NOTE:
I am using v2 of the API, so you would need to update to url to v3 if using that.
In the file object I get from the google filepicker v2 API, I don't get back a single URL that supports the change made in authentication. I had to concat the file.selfLink string to make the new URL work
var url = file.selfLink + "?alt=media&source=downloadUrl";
ORIGINAL ANSWER:
Is it possible that https://cloud.google.com/blog/products/application-development/upcoming-changes-to-the-google-drive-api-and-google-picker-api is your problem?:
download calls to files.get, revisions.get and files.export endpoints which authenticate using the access token in the query parameter will no longer be supported.
Only requests that download media content (alt=media) are affected by this change.
The access token should be provided in the HTTP header, like Authorization: Bearer oauth2-token or, if that's not possible, follow the workarounds provided in the referenced documentation:
For file downloads, redirect to the webContentLink which will instruct the browser to download the content. If the application wants to display the file to the user, they can simply redirect to the alternateLink in v2 or webViewLink in v3.
For file exports, redirect to the export link in exportLinks with the desired mime type which will instruct the browser to download the content.
Reference:
Changes in authorization to Google Drive API
Authorization via HTTP header
v2 files get documentation
v3 files get documentation

How do I get the signed document after the embedded signing ceremony completes?

Implementing a code of Embedded Signing in MVC C# Project. When I post for the sign document, It's redirecting to DocuSign page and it will redirect to return URL. using below code
private const string returnUrl = "http://localhost:5050/DSReturn";
...
return Redirect(viewUrl.Url);
Here I want to get that signed document in response instead of email. How this is possible? or is there any other way to get signed document after finish signature process?
You would make the API call to the "document" resource (.../documents/{documentId or constant}).
The post-signing redirect URL is for the purposes of continuing your web workflow. The "event" parameter allows your web application to generate the correct page or results. For example, in the "Loan Co" example at the Dev Center generates a post-signing page that has links for the document, which in turn result in the API call to retrieve the document. In a real-world integration, the redirect URL is not a reliable indicator that the envelope is "completed". For example, the signer could close the browser before the redirect was executed, or the envelope may have subsequent signers. The Connect service provides a much more reliable trigger for downloading the documents.
Expanding on what #WTP mentioned, you have a couple of approaches. First is via a raw API call using the /v2/accounts/{accountId}/envelopes/{envelopeId}/documents/{documentId} endpoint and retrieving the file from the response. More information can be found here.
Another option you may or may not be aware of is using the DocuSign Client NuGet package. Your code would then look something like this pseudocode:
Stream documentStream = EnvelopesApi.GetDocument(accountId, envelopeId, documentId);
If you are not using the NuGet package yet, keep in mind there is setup work that you will have to do to set-up the EnvelopesApi. That information can be found here.

How to generate BinarySecurityToken (X509PKIPathv1) from .p12 file

I am trying to consume a Java web service from a C# client. The service requires BinarySecurityToken element with value type X509PKIPathv1.
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1">
MIIH......
</wsse:BinarySecurityToken>
Since WCF does not support X509PKIPathv1 value type, I am generating the SOAP message by hand, signing it using the SignedXml class, encrypting it using the EncryptedXml and sending it using the WebClient class. As for the value of BinarySecurityToken element, I used the value generated in SoapUI for the same certificate, and it works.
But, I would like to be able to generate this value programmatically from .p12 file, and not having to paste it from SoapUI again every time when the certificate expires.
The WS-Security documentation is a bit vague, so I am not sure how to go about it. This is all the information it gives about this token type:
#X509PKIPathv1: An ordered list of X.509 certificates packaged in a PKIPath
How to generate this value from .p12 file in C#? SoapUI does it somehow.
So this may not be a fully solution to your problem but it may help you out somewhat.
This:
#X509PKIPathv1: An ordered list of X.509 certificates packaged in a PKIPath
means is a asn1 sequence or chain of certificates that you have used to sign your message. You can even see it here.
To give some context asn1 is way of representing data in way independent of the machine you are using. This data is binary and not human readable so you transform it to bade 64 and that is what you see in that field.
I am not entirely sure what the exact content of your .p12 file is but at the very least I assume it has the certificate of the private key you used to sign your message and maybe the chain until the publicly trusted certificate or CA.
I am mostly a C++ developer and I know openssl provides a C like api to read a certificate manipulate the underlying asn1 structure and the output it as a string.
Sorry for not providing with a greater level of detail or a code example

How safe or dangerous it is to use "UserAgent" of the request to identify the origin of the request?

I am developing an SMS service which sends SMS to the destination numbers using Twilio as an SMS provider. Twilio is suppose to send a POST request to my web service as and when the status of the message is updated (i.e., sent, delivered, etc).
In order to make sure that the POST request is not sent by anyone else than Twilio, I am validating UserAgent of the request as below.
If ((HttpRequest)request.OriginalRequest).UserAgent.StartsWith("TwilioProxy/"))
{
return true;
}
Currently I am getting "TwilioProxy/1.0" as User Agent in each of the POST action, where I believe the version number can be changed in future, so I have skipped it from validation.
Is it possible to receive a request with the same user agent (something starting to "TwilioProxy/") from any other origin than Twilio? Is it safe to rely on UserAgent for this type of verification?
Any inputs/ suggestions on this will be much helpful to me.
Thanks
Twilio developer evangelist here.
As the comments have mentioned, it is trivial to spoof a header and since the UserAgent header for Twilio is very simple, then it is unreliable to rely on it.
However, if you are interested in validating that requests are made by Twilio then you need to check out how we sign requests to ensure they are not malicious.
Here's how it works:
Turn on TLS on your server and configure your Twilio account to use HTTPS urls.
Twilio assembles its request to your application, including the final URL and any POST fields (if the request is a POST).
If your request is a POST, Twilio takes all the POST fields, sorts them by alphabetically by their name, and concatenates the parameter name and value to the end of the URL (with no delimiter).
Twilio takes the resulting string (the full URL with query string and all POST parameters) and signs it using HMAC-SHA1 and your AuthToken as the key.
Twilio sends this signature in an HTTP header called X-Twilio-Signature
Then to verify that this X-Twilio-Signature contains a valid signature, you need to do the following in your application:
Take the full URL of the request URL you specify for your phone number or app, from the protocol (https...) through the end of the query string (everything after the ?).
If the request is a POST, sort all of the POST parameters alphabetically (using Unix-style case-sensitive sorting order).
Iterate through the sorted list of POST parameters, and append the variable name and value (with no delimiters) to the end of the URL string.
Sign the resulting string with HMAC-SHA1 using your AuthToken as the key (remember, your AuthToken's case matters!).
Base64 encode the resulting hash value.
Compare your hash to ours, submitted in the X-Twilio-Signature header. If they match, then you're good to go.
Within our official libraries, we include a request validator that can do all of this for you. There is an example of doing this in C# in the documentation.
Let me know if this helps at all.

Signing Soap request with certificate

I'd like to sign a Soap request (.NET 3.5, C#) with a certificate stored in the computer (reading of certificate is ok).
I don't want the request to be encrypted (that's what I get when I change Security.Mode and Security.Message properties on WSHttpBinding). I am looking for a signed Soap header.
After reading tons of articles on MSDN, blog, StackOverflow... I came up with this approach: using IClientMessageInspector and method BeforeSendRequest. I can set a breakpoint in it and see my request, but how to modify its XML content?
Modifying the message is possible - for sample code and explanations see
http://www.codeproject.com/KB/WCF/ExtendingWCF_PartI.aspx
http://wcfpro.wordpress.com/2011/03/29/iclientmessageinspector/
http://weblogs.asp.net/paolopia/archive/2007/08/23/writing-a-wcf-message-inspector.aspx
Basically you copy the Message to an XML Doc as a buffered copy, modify the XML, then create a new Message from that modified XML and assign the new Message to the ref Message param...

Categories