Unable to parse the saml service provider metadata - c#-4.0

I have metadata provided by service provider.
I am using System.IdentityModel.Metadata; namespace to parse this metadata.
Below is piece of code to parse metadata.
using (XmlReader reader = XmlReader.Create(new StringReader(metadata)))
{
System.IdentityModel.Metadata.MetadataSerializer ser = new System.IdentityModel.Metadata.MetadataSerializer();
var metadataObject = ser.ReadMetadata(reader);
var samlMetadata = ((EntityDescriptor)metadataObject);
entityIdTextBox.Text = samlMetadata.EntityId.Id;
}
I am unable to parse this metadata and getting below error message.
ID3276: The signing credentials cannot be resolved because signed XML does not contain a SecurityKeyIdentifier.
Below is service provider metadata.
<md:EntityDescriptor ID="V.phzM5jUbn3C.zk3RrwXxXaQiH" cacheDuration="PT1440M" entityID="https://PF-DEMO1" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"><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="#V.phzM5jUbn3C.zk3RrwXxXaQiH"><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>45KpBmol54EyK76KTKqFPMp4aDzzSVCLAu7CZ7SYq8A=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>CmHeuxi5PXdKpVoz3EiWIMa2VyUA49A6GdxokjyEk9Ma2UlWTMD9QM3lExwgtGIhPpjxOJxG2ynF7lFxyp6CvI4DaCsC787K9oo32gth9fCiKJrqgFeX0JSeRjjmZvkwbg+yuj2CMZ+0bAUQNE5cv+QlESetySARQjtx+GUXmAA=</ds:SignatureValue></ds:Signature><md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIB8TCCAVqgAwIBAgIGATDbjNSDMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9RdWljayBTdGFydCBBcHAxEjAQBgNVBAMTCWxvY2FsaG9zdDAgFw0xMTA2MjkxMzE4MTdaGA8yMTExMDYwNTEzMTgxN1owOzELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1F1aWNrIFN0YXJ0IEFwcDESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCCtsj/v026YKYT/VPBdcK3tfxVdGZ0caA0kmwyr9+5yTVxp4rVGnkgKP+WL5YVaOJU+Wcj75yNvvEYx4/Vgtxhf0NLiGp1pWaEuRrC2aPrmx/0vt/0gdHLaUXq7Jj0cOhSgq+SM/wjKqT/+cED932UblZht3jFOuQvf3bTqosr8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAF9Y0gznNwteCSn8cpgepzgYEgyrZtLJNc2eI5aEl9CwiyV+6oOeXVm1jZjcT9eOfusnJjHzr1AQdHMcDSSRAsevqYnDC9bpvb1SAZJq8HHHFJ7WTQtLLscDGpyPbopOJ2fJUWxkJcjUjmUIJuSwYGKj1l9wkbF1tK2xqjJDPOUR</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://10.164.43.248:9031/sp/SLO.saml2"/><md:AssertionConsumerService index="0" Location="https://10.164.43.248:9031/sp/ACS.saml2" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true"/><md:AttributeConsumingService index="0"><md:ServiceName xml:lang="en">AttributeContract</md:ServiceName><md:RequestedAttribute Name="http://schemas.xmlsoap.org/claims/UPN"/><md:RequestedAttribute Name="http://schemas.auth360.net/2012/01/requestcontext/claims/x-am-mail"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/claims/Group"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"/><md:RequestedAttribute Name="memberOf"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/uid"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/claims/EmailAddress"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid"/><md:RequestedAttribute Name="http://schemas.efactum.net/ws/2008/identity/claims/fid"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid"/><md:RequestedAttribute Name="http://schemas.auth360.net/2012/01/requestcontext/claims/x-am-uid"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/claims/CommonName"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"/><md:RequestedAttribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod"/><md:RequestedAttribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"/><md:RequestedAttribute Name="http://schemas.efactum.net/claims/role"/><md:RequestedAttribute Name="http://schemas.efactum.net/claims/emailaddress"/></md:AttributeConsumingService></md:SPSSODescriptor><md:ContactPerson contactType="administrative"/></md:EntityDescriptor>
Please advise for same.

Related

Unable to cast object of type 'Microsoft.Graph.GroupMembersCollectionWithReferencesPage' to type 'Microsoft.Graph.Group'

Unable to cast object of type 'Microsoft.Graph.GroupMembersCollectionWithReferencesPage' to type 'Microsoft.Graph.Group'.
Please give me any solution , I got above error when I try to fetch azure group members by using Microsoft graph API.
I used this namespace (using Group = Microsoft.Graph.Group;)
var members = (Group)teamClient.Groups[itemmembers.Id].Members.Request().GetAsync().Result;
What i need to do to fix it , u need to configure my azure portal settings or i need to modify azure function code
It looks like you may be using a TeamClient object instead of a GraphServiceClient object. This is how to get it with a GraphServiceClient object:
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var members = await graphClient.Groups["{group-id}"].Members.Request()
.GetAsync().GetAwaiter().GetResult();

How to get Vault secret through Terraform

I have created the key/secret pair in Vault UI. Trying to get the Vault's secret through Terraform.
Please share thoughts!
You need to define a vault provider, and fetch it as a data object. Here's a simple example:
provider "vault" {
address = "https://my-vault-address.com"
skip_tls_verify = true
token = "xxx"
}
data "vault_generic_secret" "my_secret" {
path = "secret/path/to/mysecret"
}
Then in order to use it:
...
pass = data.vault_generic_secret.my_secret.data["password"]
...

Azure UserDelegation Key Exception

I am trying to generate UserDelegationKey for my Azure Storage Blob but i am getting an exception:
Can not instantiate Stax reader for XML source type class org.codehaus.stax2.io.Stax2ByteArraySource (unrecognized type)
This Exception occurs when i call getUserDelegationKey on BlobContainerAsyncClient
Version of my azure-storage-blob library is 12.12.0
Below is the code snippet
private void uploadNextWeekReportToAzure() {
BlobServiceAsyncClient blobServiceAsyncClient = blobServiceClientBuilder
.credential(new DefaultAzureCredentialBuilder().build())
.buildAsyncClient();
BlobContainerAsyncClient blobContainerAsyncClient = blobServiceAsyncClient.getBlobContainerAsyncClient("container name");
BlobAsyncClient blobAsyncClient = blobContainerAsyncClient.getBlobAsyncClient("blob name");
OffsetDateTime keyStart = OffsetDateTime.now();
OffsetDateTime keyExpiry = OffsetDateTime.now().plusDays(7);
blobServiceAsyncClient.getUserDelegationKey(keyStart,keyExpiry)
.doOnError(throwable -> log.error("Exception occurred:{}",throwable.getMessage()))
.doOnSuccess(userDelegationKey -> {
log.info("UserDelegationKey:{}",userDelegationKey.getValue());
String saSToken = generateSaSToken(blobAsyncClient, userDelegationKey);
log.info("SAS TOKEN:{}",saSToken);
})
.subscribe();
}
private String generateSaSToken(BlobAsyncClient blobAsyncClient,
UserDelegationKey userDelegationKey) {
BlobContainerSasPermission blobContainerSasPermission = new BlobContainerSasPermission()
.setReadPermission(true);
BlobServiceSasSignatureValues builder = new BlobServiceSasSignatureValues(
OffsetDateTime.now().plusDays(1), blobContainerSasPermission)
.setProtocol(SasProtocol.HTTPS_ONLY);
return String
.format("https://%s.blob.core.windows.net/%s/%s?%s", blobAsyncClient.getAccountName(),
blobAsyncClient.getContainerName(),
blobAsyncClient.getBlobName(),
blobAsyncClient.generateUserDelegationSas(builder, userDelegationKey));
}
Complete Exception Trace:
CallbackNotImplemented: java.lang.IllegalArgumentException: Can not instantiate Stax reader for XML source type class org.codehaus.stax2.io.Stax2ByteArraySource (unrecognized type)
Caused by: java.lang.IllegalArgumentException: Can not instantiate Stax reader for XML source type class org.codehaus.stax2.io.Stax2ByteArraySource (unrecognized type)
at io.strati.libs.forklift.com.ctc.wstx.stax.WstxInputFactory.createSR(WstxInputFactory.java:770)
at io.strati.libs.forklift.com.ctc.wstx.stax.WstxInputFactory.createXMLStreamReader(WstxInputFactory.java:345)
at com.fasterxml.jackson.dataformat.xml.XmlFactory._createParser(XmlFactory.java:631)
at com.fasterxml.jackson.dataformat.xml.XmlFactory._createParser(XmlFactory.java:29)
at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:1124)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3643)
at com.azure.core.util.serializer.JacksonAdapter.deserialize(JacksonAdapter.java:281)
at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.deserializeBody(HttpResponseBodyDecoder.java:169)
at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.lambda$decodeByteArray$1(HttpResponseBodyDecoder.java:105)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2397)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoCacheTime.subscribeOrReturn(MonoCacheTime.java:143)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107)
at reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onNext(FluxDoOnEach.java:173)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:120)
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151)
at reactor.core.publisher.FluxDelaySubscription$DelaySubscriptionMainSubscriber.onNext(FluxDelaySubscription.java:188)
at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99)
at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99)
at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.onNext(FluxTimeout.java:179)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:284)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151)
at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99)
at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:173)
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
at reactor.core.publisher.Operators$MonoInnerProducerBase.complete(Operators.java:2663)
at reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:180)
at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onComplete(MonoFlatMapMany.java:260)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:150)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:150)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159)
at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onComplete(FluxDoFinally.java:145)
at reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:212)
at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:269)
at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:401)
at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:416)
at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:470)
at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:685)
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94)
Try this code to generate user delegation key and SAS
String endpoint = String.format(Locale.ROOT, "https://%s.blob.core.windows.net", "accountName");,
blobServiceClient = new BlobServiceClientBuilder().endpoint(endpoint).credential(new DefaultAzureCredentialBuilder().build()).buildClient();
keyStart = OffsetDateTime.now();
keyExpiry = OffsetDateTime.now().plusDays(7);
userDelegationKey = blobServiceClient.getUserDelegationKey(keyStart, keyExpiry);
BlobContainerSasPermission blobContainerSas = new BlobContainerSasPermission();
blobContainerSas.setReadPermission(true);
BlobServiceSasSignatureValues blobServiceSasSignatureValues = new BlobServiceSasSignatureValues(keyExpiry,blobContainerSas);
BlobContainerClient blobContainerClient=blobServiceClient.getBlobContainerClient("containerName");
if (!blobContainerClient.exists())
blobContainerClient.create();
String sas = blobContainerClient.generateUserDelegationSas(blobServiceSasSignatureValues, userDelegationKey);
For more information refer this link
You may also check this method to Generate Key
The Get User Delegation Key operation gets a key that can be used to sign a user delegation SAS (shared access signature). A user delegation SAS grants access to resources in the Blob service using Azure Active Directory (Azure AD) credentials.
For more information refer this link

COS access policies interface vs terraform

In interface I can go to COS Bucket Access Policies and easily assign policy that then looks more or less like:
Cloud Object Storage service
serviceInstance string equals foo-bar, resource string equals foo-bar-pcaps, resourceType string equals bucket
I'm struggling to find a way to do the same via terraform because whenever I try with the proper TF code like:
resource "ibm_iam_service_policy" "policy_pcaps" {
iam_service_id = ibm_iam_service_id.serviceID_pcaps.id
roles = ["Writer"]
resources {
service = "cloud-object-storage"
resource = ibm_cos_bucket.pcaps.id
}
}
I'm ending up with
Cloud Object Storage service
resource string equals crn:v1:bluemix:public:cloud-object-storage:global:a/27beaaea79a<redacted>34dd871b:8b124bc6-147c-47ba-bd47-<redacted>:bucket:foo-bar-pcaps:meta:rl:us-east
The problem is that the Writer policy that is required here does not work properly with that policy details.
How to achieve something similar to the first policy with Terraform?
Thanks
You can achieve this similar to this example Service Policy by using attributes.
I created a policy through the UI for Cloud Object Storage and specified the policy to contain a bucket name. Then I used:
ibmcloud iam access-group-policy GROUP_NAME POLICY_ID --output JSON
to get a better understanding of the policy.
With that I created this sample terraform snippet and tested it. It is creating the IAM access group + policy:
resource "ibm_iam_access_group" "accgrp_cos" {
name = "test_cos"
}
resource "ibm_iam_access_group_policy" "policy" {
access_group_id = ibm_iam_access_group.accgrp_cos.id
roles = ["Writer"]
resources {
service = "cloud-object-storage"
attributes = {
resourceType = "bucket"
resource = "tf-test-cos"
}
}
}

Single Sign On With ACS through Multiple Applications

Simple Single Sign-On question
I Have two MVC4 applications:
**1**- http://localhost/BikeShop
ACS Relying Party:
- Name: **BikeShop**
- Return Url: **http://localhost/BikeShop**
- Token Format: **SAML 2.0**
**2**- http://localhost/BikePartsShop
ACS Relying Party:
- Name: **BikePartsShop**
- Return Url: **http://localhost/BikePartsShop**
- Token Format: **SAML 2.0**
The Scenario I have
I access BikeShop and the ACS Login Page is presented and I choose my Identity.
I now can do stuff on BikeShop.
Then I access BikePartsShop and the ACS Login Page is presented and I can choose my Identity.
The Scenario I must have
I access BikeShop and the ACS Login Page is presented and I choose my Identity.
I now can do stuff on BikeShop.
Then I access BikePartsShop and the ACS authorizes the same Identity
used in the BikeShop without further user intervention.
Has anyone implemented this scenario?
Best Regards, and thank you!
You can use the ACS management service to configure multiple reply addresses for the same relying party. See this link for details on how to add an RP. From the linked code sample, register more addresses as follows:
RelyingParty relyingParty = new RelyingParty()
{
Name = "BikeShop",
AsymmetricTokenEncryptionRequired = false,
TokenType = "SAML_2_0",
TokenLifetime = 3600
};
svc.AddToRelyingParties(relyingParty);
RelyingPartyAddress realm = new RelyingPartyAddress()
{
Address = "http://localhost/",
EndpointType = "Realm"
};
RelyingPartyAddress replyAddress1 = new RelyingPartyAddress()
{
Address = "http://localhost/BikeShop",
EndpointType = "Reply"
};
RelyingPartyAddress replyAddress2 = new RelyingPartyAddress()
{
Address = "http://localhost/BikePartsShop",
EndpointType = "Reply"
};
svc.AddRelatedObject(relyingParty, "RelyingPartyAddresses", realmAddress);
svc.AddRelatedObject(relyingParty, "RelyingPartyAddresses", replyAddress1);
svc.AddRelatedObject(relyingParty, "RelyingPartyAddresses", replyAddress2);
svc.SaveChanges(SaveChangesOptions.Batch);
Try out this code to help you forward to a specific identity provider, if you can figure out how to remember which identity provider they last used. The last login should be stored so that you will automatically 302 back to your app.
public IdentityProvider GetIdentityProvider(string identityProviderName, string realm , string audienceUri )
{
// acs config parameters
string acsNamespace = ConfigurationManager.AppSettings["ida:Namespace"];
realm = realm ?? Uri.EscapeDataString(ConfigurationManager.AppSettings["ida:Realm"]);
audienceUri = audienceUri ?? ConfigurationManager.AppSettings["ida:AudienceUri"];
string returnPath = Uri.EscapeDataString("/home/index");
var newReplyTo =
Uri.EscapeDataString(audienceUri.Replace(new Uri(audienceUri).Authority,
HttpContext.Current.Request.Url.Authority));
// retrieve current identity providers
string idpDiscoveryUrl = string.Format("{0}v2/metadata/IdentityProviders.js?protocol=wsfederation&realm={1}&reply_to={2}&context=rm%3d0%26id%3dpassive%26ru%3d{3}&request_id=&version=1.0", acsNamespace, realm, newReplyTo, returnPath);
string response = null;
using (var client = new WebClient()) {
response = client.DownloadString(idpDiscoveryUrl);
}
List<IdentityProvider> identityProviders = JsonConvert.DeserializeObject<List<IdentityProvider>>(response);
// lookup provider for tenant
var identityProvider = identityProviders.Where(i => i.Name == identityProviderName).FirstOrDefault() ?? new IdentityProvider();
return identityProvider;
}

Resources