ITfoxtec SAML 2.0 encrypt assertion - encryption

Is it possible to encrypt the assertion response with ITfoxtec Identity Saml2 (open source - https://itfoxtec.com/identitysaml2)? Haven't been able to find anything.
The GitHub site (https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2) mentions decrypting but not encrypting. Doesn't seem to be any examples on encrypting either.
Any help is appreciated. Thanks.

In saml2postbinding class, replace BindInternal method with below code.
protected override Saml2PostBinding BindInternal(Saml2Request saml2RequestResponse, string messageName)
{
BindInternal(saml2RequestResponse);
var element1 = XmlDocument.CreateElement("saml2", "EncryptedAssertion", "urn:oasis:names:tc:SAML:2.0:assertion");
XmlDocument xmlDoc = new XmlDocument();
var assertionElements = XmlDocument.DocumentElement.SelectNodes($"//*[local-name()='{Saml2Constants.Message.Assertion}']");
var assertionElement = (assertionElements[0] as XmlElement).ToXmlDocument().DocumentElement;
var certificate = ITfoxtec.Identity.Saml2.Util.CertificateUtil.Load(#"F:\IT-FoxTec-Core Copy\ITfoxtec.Identity.Saml2-master (1)\ITfoxtec.Identity.Saml2-master\test\TestIdPCore\itfoxtec.identity.saml2.testwebappcore_Certificate.crt");
var wrappedAssertion = $#"<saml2:EncryptedAssertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"">{assertionElement.OuterXml}</saml2:EncryptedAssertion>";
xmlDoc.LoadXml(wrappedAssertion);
var elementToEncrypt = (XmlElement)xmlDoc.GetElementsByTagName("Assertion", Saml2Constants.AssertionNamespace.OriginalString)[0];
element1.InnerXml = wrappedAssertion.ToXmlDocument().DocumentElement.SelectNodes($"//*[local-name()='{Saml2Constants.Message.Assertion}']")[0].OuterXml;
var element2 = wrappedAssertion.ToXmlDocument().DocumentElement;
var childNode = XmlDocument.GetElementsByTagName("Assertion", Saml2Constants.AssertionNamespace.OriginalString)[0];
XmlDocument.DocumentElement.RemoveChild(childNode);
var status = XmlDocument.DocumentElement[Saml2Constants.Message.Status, Saml2Constants.ProtocolNamespace.OriginalString];
XmlDocument.DocumentElement.InsertAfter(element1, status);
if (certificate == null) throw new ArgumentNullException(nameof(certificate));
var encryptedData = new EncryptedData
{
Type = EncryptedXml.XmlEncElementUrl,
EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url)
};
var algorithm = true ? EncryptedXml.XmlEncRSAOAEPUrl : EncryptedXml.XmlEncRSA15Url;
var encryptedKey = new EncryptedKey
{
EncryptionMethod = new EncryptionMethod(algorithm),
};
var encryptedXml = new EncryptedXml();
byte[] encryptedElement;
using (var encryptionAlgorithm = new AesCryptoServiceProvider())
{
encryptionAlgorithm.KeySize = 256;
encryptedKey.CipherData = new CipherData(EncryptedXml.EncryptKey(encryptionAlgorithm.Key, (RSA)certificate.PublicKey.Key, true));
encryptedElement = encryptedXml.EncryptData(elementToEncrypt, encryptionAlgorithm, false);
}
encryptedData.CipherData.CipherValue = encryptedElement;
encryptedData.KeyInfo = new KeyInfo();
encryptedData.KeyInfo.AddClause(new KeyInfoEncryptedKey(encryptedKey));
EncryptedXml.ReplaceElement((XmlElement)xmlDoc.GetElementsByTagName("Assertion", Saml2Constants.AssertionNamespace.OriginalString)[0], encryptedData, false);
EncryptedXml.ReplaceElement((XmlElement)XmlDocument.GetElementsByTagName("Assertion", Saml2Constants.AssertionNamespace.OriginalString)[0], encryptedData, false);
if ((!(saml2RequestResponse is Saml2AuthnRequest) || saml2RequestResponse.Config.SignAuthnRequest) && saml2RequestResponse.Config.SigningCertificate != null)
{
Cryptography.SignatureAlgorithm.ValidateAlgorithm(saml2RequestResponse.Config.SignatureAlgorithm);
XmlDocument = XmlDocument.SignDocument(saml2RequestResponse.Config.SigningCertificate, saml2RequestResponse.Config.SignatureAlgorithm, CertificateIncludeOption, saml2RequestResponse.Id.Value);
}
PostContent = string.Concat(HtmlPostPage(saml2RequestResponse.Destination, messageName));
return this;
}
Here certificate is public key certificate for any relying party.

I m sorry to say that assertion response encryption is currently not supported.
You are Welcome to create an issue on the missing encryption funktionalitet.
If you implement the functionality please share the code.

Related

SECNamedCurves.getByName("secp256r1") showing NoSuchMethod exception in Android Q

When I generate public key by using ECDH_KeyGeneration.getPublicKey() in robovm library.
it throws an exception - NoSuchMethodException.
This problem occurred in Android Q only . till android pie it is working fine.
X9ECParameters ecp = SECNamedCurves.getByName("secp256r1");
ECDomainParameters domainParams = new ECDomainParameters(ecp.getCurve(),
ecp.getG(), ecp.getN(), ecp.getH(),
ecp.getSeed());
// Generate a private key and a public key
AsymmetricCipherKeyPair keyPair;
ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(domainParams, new SecureRandom());
ECKeyPairGenerator generator = new ECKeyPairGenerator();
generator.init(keyGenParams);
keyPair = generator.generateKeyPair();
ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters) keyPair.getPrivate();
ECPublicKeyParameters publicKey = ((ECPublicKeyParameters) keyPair.getPublic());
mPrivateKeyBytes2 = privateKey.getD().toByteArray();
String str = Hex.toHexString(publicKey.getQ().getEncoded(false));
Lcom/android/org/bouncycastle/asn1/sec/SECNamedCurves; or its super classes (declaration of 'com.android.org.bouncycastle.asn1.sec.SECNamedCurves' appears in /apex/com.android.runtime/javalib/bouncycastle.jar)
at projects.athansys.com.athandoctorassist.helper.ECDH_KeyGeneration.getPublicKey(ECDH_KeyGeneration.java:25)
The following code will help you, you can generate algorithm using bouncy castle library:
private static ECDsa GetEllipticCurveAlgorithm(string privateKey)
{
var keyParams = (ECPrivateKeyParameters)PrivateKeyFactory
.CreateKey(Convert.FromBase64String(privateKey));
var normalizedECPoint = keyParams.Parameters.G.Multiply(keyParams.D).Normalize();
return ECDsa.Create(new ECParameters
{
Curve = ECCurve.CreateFromValue(keyParams.PublicKeyParamSet.Id),
D = keyParams.D.ToByteArrayUnsigned(),
Q =
{
X = normalizedECPoint.XCoord.GetEncoded(),
Y = normalizedECPoint.YCoord.GetEncoded()
}
});
}
and generate the token in the following way:
var signatureAlgorithm = GetEllipticCurveAlgorithm(privateKey);
ECDsaSecurityKey eCDsaSecurityKey = new ECDsaSecurityKey(signatureAlgorithm)
{
KeyId = settings.Apple.KeyId
};
var handler = new JwtSecurityTokenHandler();
var token = handler.CreateJwtSecurityToken(
issuer: iss,
audience: AUD,
subject: new ClaimsIdentity(new List<Claim> { new Claim("sub", sub) }),
expires: DateTime.UtcNow.AddMinutes(5),
issuedAt: DateTime.UtcNow,
notBefore: DateTime.UtcNow,
signingCredentials: new SigningCredentials(eCDsaSecurityKey, SecurityAlgorithms.EcdsaSha256));

Retrieving CRM 4 entities with custom fields in custom workflow activity C#

I'm trying to retrieve all phone calls related to opportunity, which statecode isn't equal 1. Tried QueryByAttribute, QueryExpression and RetrieveMultipleRequest, but still has no solution.
Here some code i wrote.
IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
IWorkflowContext context = contextService.Context;
ICrmService crmService = context.CreateCrmService(true);
if (crmService != null)
{
QueryByAttribute query = new Microsoft.Crm.Sdk.Query.QueryByAttribute();
query.ColumnSet = new Microsoft.Crm.Sdk.Query.AllColumns();
query.EntityName = EntityName.phonecall.ToString();
query.Attributes = new string[] { "regardingobjectid" };
query.Values = new string[] { context.PrimaryEntityId.ToString() };
RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();
retrieve.Query = query;
retrieve.ReturnDynamicEntities = true;
RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(retrieve);
}
return ActivityExecutionStatus.Closed;
}
And almost same for QueryExpression
QueryExpression phCallsQuery = new QueryExpression();
ColumnSet cols = new ColumnSet(new string[] { "activityid", "regardingobjectid" });
phCallsQuery.EntityName = EntityName.phonecall.ToString();
phCallsQuery.ColumnSet = cols;
phCallsQuery.Criteria = new FilterExpression();
phCallsQuery.Criteria.FilterOperator = LogicalOperator.And;
phCallsQuery.Criteria.AddCondition("statuscode", ConditionOperator.NotEqual, "1");
phCallsQuery.Criteria.AddCondition("regardingobjectid", ConditionOperator.Equal, context.PrimaryEntityId.ToString();
I always get something like Soap exception or "Server was unable to proceed the request" when debugging.
To get exception details try to use following code:
RetrieveMultipleResponse retrieved = null;
try
{
retrieved = (RetrieveMultipleResponse)crmService.Execute(retrieve);
}
catch(SoapException se)
{
throw new Exception(se.Detail.InnerXml);
}

How to consume a LOB Adapter SDK-based design-time interfaces

I'm trying to build a web-based GUI to consume custom LOB Adapter SDK-based connectors.
In particular, I would like to browse the metadata using the IMetadataResolverHandler interface.
I'm having two problems:
The first problem happens when trying to instantiate the custom adapter. My plan is to obtain an instance of the IConnectionFactory interface, through which I could get a new IConnection and connect to the target LOB system.
Since the most interesting methods in the Adapter base class are protected, I can only seem to succeed using reflection (please, see the sample code below).
The second problem happens when trying to browse the metadata from the target system. The method Browse on the IMetadataResolverHandler interface expects an instance of a MetadataLookup object that I have no idea how to obtain.
Please, see the sample code below:
static void Main(string[] args)
{
var extension = new SqlAdapterBindingElementExtensionElement();
var adapter = (Adapter) Activator.CreateInstance(extension.BindingElementType);
var isHandlerSupportedMethodInfo = adapter.GetType().GetMethod("IsHandlerSupported", BindingFlags.NonPublic | BindingFlags.Instance);
var buildConnectionUri = adapter.GetType().GetMethod("BuildConnectionUri", BindingFlags.NonPublic | BindingFlags.Instance);
var buildConnectionFactory = adapter.GetType().GetMethod("BuildConnectionFactory", BindingFlags.NonPublic | BindingFlags.Instance);
if (isHandlerSupportedMethodInfo == null || buildConnectionUri == null || buildConnectionFactory == null)
{
Console.WriteLine("Not a LOB adapter.");
Environment.Exit(1);
}
var isHandlerSupportedTHandler = isHandlerSupportedMethodInfo.MakeGenericMethod(typeof(IMetadataResolverHandler));
var isMetadataBrowseSupported = (bool)isHandlerSupportedTHandler.Invoke(adapter, new object[] { });
if (!isMetadataBrowseSupported)
{
Console.WriteLine("Metadata retrieval not supported.");
Environment.Exit(1);
}
var bindingElement = (SqlAdapterBindingElement)adapter;
bindingElement.AcceptCredentialsInUri = false;
bindingElement.InboundOperationType = InboundOperation.TypedPolling;
bindingElement.PolledDataAvailableStatement = "EXEC [dbo].[usp_IsDataAvailable]";
bindingElement.PollingStatement = "EXEC [dbo].[usp_SelectAvailableData]";
bindingElement.PollingIntervalInSeconds = 10;
var binding = new CustomBinding();
binding.Elements.Add(adapter);
var parameters = new BindingParameterCollection();
var context = new BindingContext(binding, parameters);
var credentials = new ClientCredentials();
credentials.UserName.UserName = "username";
credentials.UserName.Password = "password";
var address = (ConnectionUri) buildConnectionUri.Invoke(adapter, new []{ new Uri("mssql://azure.database.windows.net//SampleDb?InboundId=uniqueId")});
var connectionFactory = (IConnectionFactory)buildConnectionFactory.Invoke(adapter, new object[] { address, credentials, context });
var connection = connectionFactory.CreateConnection();
connection.Open(TimeSpan.MaxValue);
MetadataLookup lookup = null; // ??
var browser = connection.BuildHandler<IMetadataBrowseHandler>(lookup);
connection.Close(TimeSpan.MaxValue);
}
Answering my own question, I figured it out by inspecting the code of the "Consume Adapter Service" wizard. The key is to use the IMetadataRetrievalContract interface which, internally, is implemented using up to three LOB-SDK interfaces, and in particular IMetadataResolverHandler.
Here is code that works without reflection:
var extension = new SqlAdapterBindingElementExtensionElement();
var adapter = (Adapter) Activator.CreateInstance(extension.BindingElementType);
var bindingElement = (SqlAdapterBindingElement)adapter;
bindingElement.AcceptCredentialsInUri = false;
bindingElement.InboundOperationType = InboundOperation.TypedPolling;
bindingElement.PolledDataAvailableStatement = "EXEC [dbo].[usp_IsDataAvailable]";
bindingElement.PollingStatement = "EXEC [dbo].[usp_SelectAvailableData]";
bindingElement.PollingIntervalInSeconds = 10;
var binding = new CustomBinding();
binding.Elements.Add(adapter);
const string endpoint = "mssql://azure.database.windows.net//SampleDb?InboundId=unique";
var factory = new ChannelFactory<IMetadataRetrievalContract>(binding, new EndpointAddress(new Uri(endpoint)));
factory.Credentials.UserName.UserName = "username";
factory.Credentials.UserName.Password = "password";
factory.Open();
var channel = factory.CreateChannel();
((IChannel)channel).Open();
var metadata = channel.Browse(MetadataRetrievalNode.Root.DisplayName, 0, Int32.MaxValue);
((IChannel) channel).Close();
factory.Close();

Sending parameter along URL actionscript

As part of a mobile app I'm building I have to authenticate trough the API of Last.FM.
As documented on their website I tried to format to url correctly but appearently I'm doing something wrong because I get error:
Error #2044: Unhandled ioError:. text=Error #2032: Stream Error. URL: https://ws.audioscrobbler.com/2.0/?method=auth.getMobileSession
Last.FM documentation: http://www.last.fm/api/mobileauth
My code below:
var username:String = "xxxxxxx";
var password:String = "xxxxxxxxxxxx";
var api_key:String = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
var secret:String = "xxxxxxxxxxxxxxxxxxxxxx";
var api_sig:String = MD5.hash( "api_key" + api_key + "methodauth.getMobileSessionpassword" + password + "username" + secret);
var request:URLRequest = new URLRequest("https://ws.audioscrobbler.com/2.0/?method=auth.getMobileSession");
var variables:URLVariables = new URLVariables();//create a variable container
variables.username =username;
variables.password = password;
variables.api_key = api_key;
variables.api_sig = api_sig;
request.data = variables;
request.method = URLRequestMethod.POST;//select the method as post/
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, handleComplete);
loader.load(request);//send the request with URLLoader()
Does someone know the answer?
Try to use HTTPService instead of URLLoader. Smth like this:
var http:HTTPService = new HTTPService();
http.useProxy = false;
http.resultFormat = "e4x";
http.method = "POST";
http.url = "https://ws.audioscrobbler.com/2.0/?method=auth.getMobileSession";
var variables:Object = {};
variables.username = username;
variables.password = password;
variables.api_key = api_key;
variables.api_sig = api_sig;
var token:AsyncToken = http.send(variables);
var responder:Responder = new Responder(handleRequestComplete, handleError);
token.addResponder(responder);
Where handleRequestComplete and handleError are your handlers for the request results:
private function handleRequestComplete(event:ResultEvent):void
{
// your code here
}
private function handleError(event:FaultEvent):void
{
// your code here
}

Remote Image with basic authentication?

I would like to load a an image from an external domain and I have the below so far:
private function get_coverArt(coverArtID:String):void
{
var requestString:String = "/rest/getCoverArt.view?v=1.5.0&c=AirSub&id=" + coverArtID;
var requestURL:String = subServerURL + requestString;
myCoverArtLoader = new URLLoader();
var myRequest:URLRequest = new URLRequest();
var authHeader:URLRequestHeader = new URLRequestHeader();
authHeader.name = 'Authorization';
authHeader.value = 'Basic ' + credentials;
myRequest.requestHeaders.push(authHeader);
myRequest.url = requestURL;
myRequest.method = URLRequestMethod.GET;
myCoverArtLoader.dataFormat = URLLoaderDataFormat.BINARY;
myCoverArtLoader.addEventListener(Event.COMPLETE, set_coverArt);
myCoverArtLoader.load(myRequest);
}
private function set_coverArt(evt:Event) : void {
coverArtImg = new Image();
var loader:Loader = new Loader();
loader.loadBytes(myCoverArtLoader.data);
coverArtImg.source = loader;
}
This does not seem to work - any help?
Thanks!
Try setting the source directly like so:
private function set_coverArt(evt:Event) : void {
coverArtImg = new Image();
coverArtImg.source = myCoverArtLoader.data;
}
Also, check your authentication, here's a question I answered regarding the auth :
Actionscript 3: Reading an RSS feed that requires authentication

Resources