var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
services.AddAuthentication().AddFacebook(facebookOptions =>
{facebookOptions.AppId = "xxxxx";
facebookOptions.AppSecret = "xxxxx";
});
services.AddAuthentication().AddGoogle(googleOptions =>
{ googleOptions.ClientId = configuration["Authentication:Google:ClientId"];
googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"];
});`
For FaceBook works fine. What is the problem for Google? I cant find any kind of package in the NuGet.
Do not forget to install Microsoft.AspNetCore.Authentication.Google nuget package.
Related
I am creating a web host that uses SOAPCore for the middleware. Once I build the web host, I am unsure if it is possible to add in new SOAPCore endpoints for specific paths.
Here is how I build the web host:
var webHost = new WebHostBuilder().UseKestrel(x => x.AllowSynchronousIO = true).UseUrls($"http://*:8381").UseStartup<StartupClass>().ConfigureLogging(x =>
{
x.SetMinimumLevel(LogLevel.Trace);
x.AddDebug();
x.AddConsole();
}).Build()
Here is the configure method in the StartupClass
public void Configure(IApplicationBuilder app)
{
app.UseSoapEndpoint<SoapInterface1>(options =>
{
options.Path = "/path1";
options.UseBasicAuthentication = false;
options.EncoderOptions = new[]
{
new SoapEncoderOptions
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None),
WriteEncoding = Encoding.UTF8,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
}
};
options.SoapSerializer = SoapSerializer.XmlSerializer;
options.CaseInsensitivePath = true;
options.IndentXml = false;
options.OmitXmlDeclaration = true;
});
}
I have found https://gist.github.com/Tratcher/ae23d9a7b4c8c7c37d7a769ad68bd228 that shows how to add and remove ports using the kestrel config. I am wondering if there is something similar (or better) that will allow me to programmatically add in the SOAP endpoints?
Specifically, adding in something like this after the web host is built (they may or may not use the same interface):
app.UseSoapEndpoint<SoapInterface2>(options =>
{
options.Path = "/path2";
options.UseBasicAuthentication = false;
options.EncoderOptions = new[]
{
new SoapEncoderOptions
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None),
WriteEncoding = Encoding.UTF8,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
}
};
options.SoapSerializer = SoapSerializer.XmlSerializer;
options.CaseInsensitivePath = true;
options.IndentXml = false;
options.OmitXmlDeclaration = true;
});
Any help would be greatly appreciated.
How to validate uploaded ARM Template using azure .net SDK or Fluent API ?
I want to validate my uploaded ARM template like azure portal do using azure .net SDK or Fluent API ?
For reference please see below image azure is showing message if ARM template not valid so same thing i want to implement using any .net API or REST API.
#Jim Below error I am getting:
If you want to validate your arm template, please refer to the following steps
Create a service principal and assign Contributor role to the sp
az ad sp create-for-rbac -n "MyApp"
Install Package
Install-Package Microsoft.Azure.Management.ResourceManager.Fluent -Version 1.34.0
Code
string clientId = "23****9c";
string clientSecret = "?s****/k";
string tenantDomain = "";
string subscription = "";
var creds= SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantDomain, AzureEnvironment.AzureGlobalCloud);
var restClient = RestClient.Configure()
.WithEnvironment(AzureEnvironment.AzureGlobalCloud)
.WithCredentials(creds)
.WithLogLevel(HttpLoggingDelegatingHandler.Level.BodyAndHeaders)
.Build();
ResourceManagementClient managementClient = new ResourceManagementClient(restClient);
managementClient.SubscriptionId = subscription;
//Validates whether the specified template is syntactically correct and will be accepted by Azure Resource Manager..
DeploymentValidateResultInner res = await managementClient.Deployments.ValidateAsync("<groupName>", "<deployName>", new DeploymentInner()
{
Location = "",
Properties = new DeploymentProperties()
{
ParametersLink = new ParametersLink("uri"),
TemplateLink = new TemplateLink("")
}
});
Console.WriteLine(res.Error.Message);
// get changes that will be made by the deployment if executed at the scope of resource group
WhatIfOperationResultInner res1 = await managementClient.Deployments.WhatIfAsync("<groupName>", "<deployName>", new DeploymentWhatIf() {
Location="",
Properties= new DeploymentWhatIfProperties() {
ParametersLink = new ParametersLink("uri"),
TemplateLink = new TemplateLink("")
}
});
foreach (var change in res1.Changes) {
//
}
I like that the accepted answer adds the "what if" to validation. However, Microsoft.Azure.Management.ResourceManager is deprecated, and it took me a bit to figure out a way to validate an ARM template using the replacement library: Azure.ResourceManager.
Here's a code snippet that provides template validation using the new library (it doesn't include the what-if call):
var credential = new DefaultAzureCredential();
var subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID");
var client = new ArmClient(credential, subscriptionId);
var deploymentContent = new ArmDeploymentContent(new ArmDeploymentProperties(ArmDeploymentMode.Incremental)
{
Template = BinaryData.FromString(templateContent),
Parameters = BinaryData.FromObjectAsJson(new
{
hostingPlanName = new
{
value = hostingPlanName
},
webSiteName = new
{
value = webAppName
},
skuName = new
{
value = webSkuName
},
skuCapacity = new
{
value = webSkuCapacity
},
})
});
var resourceGroupId = ResourceGroupResource.CreateResourceIdentifier(SubscriptionId!, resourceGroupName);
// This ArmDeploymentResource resource may or may not exist, but it doesn't matter - it's just a placeholder for validation
var deploymentResourceId = ArmDeploymentResource.CreateResourceIdentifier(resourceGroupId, deploymentName);
var armDeployment = client.GetArmDeploymentResource(deploymentResourceId);
var validateOperation = await armDeployment.ValidateAsync(WaitUntil.Completed, toValidate, _cancellationToken);
var validateResult = validateOperation.Value;
if (validateResult.Error != null)
{
_logger.LogEndOperation(loggerOpKey, false, validateResult.Error.Message ?? "Validation errored");
_logger.LogError(JsonConvert.SerializeObject(validateResult.Error, Formatting.Indented));
return false;
}
// Log this if you want:
string deploymentDetails = $"Deployment: {deploymentName} ProvisioningState:{validateResult.Properties.ProvisioningState}\n"
+ $" started:{validateResult.Properties.Timestamp} duration:{validateResult.Properties.Duration}\n"
+ $" correlationId:{validateResult.Properties.CorrelationId}\n"
+ $" outputs:{JsonConvert.SerializeObject(validateResult.Properties.Outputs)}";
bool succeeded = validateResult.Properties.ProvisioningState == "Succeeded";
return succeeded;
I tried a lot and now putting it here .. so I have an app service in which API Identity server and UI(Blazor) is hosted in different folders inside the same app service now i generated the rsa signing cert from
[https://damienbod.com/2020/02/10/create-certificates-for-identityserver4-signing-using-net-core/](this blog post)
now everything works fine on development even when i set hosted identity server as provider and localhost(UI and Web API) even then its working
but when i try to access the hosted API its throwing error (in log) and i am getting 401
please any helps would be appreciated
also
my identity server startup looks like this
public void ConfigureServices(IServiceCollection services)
{
var settings = config.GetSection("AppSettings").Get<AppSettings>();
X509Certificate2 rsaCertificate = null;
if (env.IsDevelopment())
{
rsaCertificate = new X509Certificate2(
Path.Combine(env.WebRootPath, "cert/rsaCert.pfx"), "password");
}
else
{
using (X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
settings.CertificateDetails.CertificateThumbPrint,
false);
// Get the first cert with the thumbprint
if (certCollection.Count > 0)
{
rsaCertificate = certCollection[0];
}
}
}
var connectionString = config.GetConnectionString("DefaultConnection");
services.AddOidcStateDataFormatterCache();
services.AddDbContext<SeatingDBContext>(x =>
{
x.UseSqlServer(connectionString);
});
services.AddIdentity<ApplicationUser, ApplicationRole>(x =>
{
x.Password.RequiredLength = 4;
x.Password.RequireDigit = false;
x.Password.RequireNonAlphanumeric = false;
x.Password.RequireUppercase = false;
}).AddEntityFrameworkStores<SeatingDBContext>().
AddDefaultTokenProviders();
services.ConfigureApplicationCookie(x =>
{
x.Cookie.Name = "IdentityServer.Cookie";
x.LoginPath = "/Auth/Login";
});
var assembly = typeof(Startup).Assembly.GetName().Name;
services.AddIdentityServer(x =>
{
x.Events.RaiseErrorEvents = true;
x.Events.RaiseFailureEvents = true;
x.Events.RaiseSuccessEvents = true;
x.Events.RaiseInformationEvents = true;
}).AddAspNetIdentity<ApplicationUser>()
.AddInMemoryIdentityResources(Configuration.GetIdentityResources())
.AddInMemoryApiScopes(Configuration.GetApiScopes())
.AddInMemoryApiResources(Configuration.GetApis())
.AddInMemoryClients(Configuration.GetClients(settings.ClientApps))
.AddSigningCredential(rsaCertificate);
// .AddValidationKey(rsaCertificate);
services.AddScoped(typeof(IRepository<,>), typeof(Repository<,>));
services.AddTransient<IUserSyncService, UserSyncService>();
services.AddControllersWithViews();
}
and my web API looks like this
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("DefaultConnection");
var settings = Configuration.GetSection("AppSettings").Get<AppSettings>();
services.AddControllers();
services.AddDbContext<SeatingDBContext>(x => x.UseSqlServer(connectionString));
services.AddScoped(typeof(IRepository<,>), typeof(Repository<,>));
services.AddAutoMapper(typeof(Startup));
services.AddScoped<IEmailService, EmailService>();
services.AddSingleton<IEmailConfiguration>(settings.EmailConfiguration);
services.AddScoped<MailSender>();
services.AddControllers();
services.AddIdentityForWebApi<ApplicationUser, ApplicationRole>(x =>
{
x.Password.RequiredLength = 4;
x.Password.RequireDigit = false;
x.Password.RequireNonAlphanumeric = false;
x.Password.RequireUppercase = false;
}).AddEntityFrameworkStores<SeatingDBContext>();
services.AddAuthentication(defaultScheme:"Bearer")
.AddIdentityServerAuthentication("Bearer", config =>
{
config.Authority = settings.ODICSettings.Authority;
config.ApiName = settings.ODICSettings.Audience;
});
services.AddAuthorization(options =>
{
options.AddPolicy("ApiScope", policy =>
{
policy.RequireAuthenticatedUser();
foreach (string scope in settings.ODICSettings.scope)
policy.RequireClaim("scope", scope);
});
});
}
You can not use the signing certificate as a HTTPS web certificate. The signing cert is only used when IdentityServer signs the JWT tokens.
You need to get a real certificate from a trusted provider (like Lets Encrypt) and install it separately as a TLS/HTTPS certificate.
Signing certs and TLS/HTTPS certificates are separate things that both needs to be configured properly.
I am trying to create azure key vault using .net core 2.1 with OpenIdConnect.
What I have tried :-
I have tried to refer following stack-overflow already question-answer
Creating Azure Key Vault using .NET assembly (Microsoft.Azure.KeyVault)
Azure Key Vault - programmatic creation
and Others
Nuget package :- Microsoft.Azure.Management.KeyVault
Code :-
private async Task AddKeyVaultAsync()
{
var clientId = "xxxx";
var tenantId = "xxxx";
var clientSecret = "xxxx";
var objectId = "xxxx";
var subscriptionId = "xxx";
// The resource group to create the vault in.
string resourceGroupName = "Vaults-Resource-Group";
// The name of the vault to create.
string vaultName = "web-app-01-vault";
var parameters = new VaultCreateOrUpdateParameters()
{
Location = "southeast asia",
Properties = new VaultProperties()
{
TenantId = Guid.Parse(tenantId),
AccessPolicies = new List<AccessPolicyEntry>()
{
new AccessPolicyEntry
{
TenantId = Guid.Parse(tenantId),
ObjectId = objectId,
Permissions = new Permissions
{
Secrets = new List<string> { "all" },
Keys = new string[] { "all" }
}
}
}
}
};
//problem in following line
var tokenCredentials = new TokenCloudCredentials(subscriptionId, token);
var keyVaultManagementClient = new KeyVaultManagementClient(tokenCredentials);
// Create the vault
await keyVaultManagementClient.Vaults.CreateOrUpdateAsync(resourceGroupName, vaultName, parameters);
}
but I am stuck at
//problem in the following line
var tokenCredentials = new TokenCloudCredentials(subscriptionId, token);
How can i create token(parameter in TokenCloudCredentials) and TokenCloudCredentials?
Which Nuget package shall i use to create TokenCloudCredentials?
I have also tried to use :-
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
to create KeyVaultManagementClient. but I am not sure that how can do it?
Is there any other(better) way to create KeyVaultManagementClient?
The code shows how to get an access token using client credential flow.
var app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithAuthority(AzureCloudInstance.AzurePublic, "{tenantID}")
.WithClientSecret(config.ClientSecret)
.Build();
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
var result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
var token = result.accessToken;
For more details, see here.
Update:
The sample of creating key vault using .net core 2.1
Before accessing Key Vault from code ensure that MSI(Managed Service Identity) is configured in Azure
To enable the use of Azure Key Vault you need to install below
packages.
PM> Install-Package Azure.Security.KeyVault.Secrets
PM> Install-Package Microsoft.Extensions.Configuration.AzureKeyVault
PM> Install-Package Azure.Identity
PM> Install-Package Azure.Extensions.AspNetCore.Configuration.Secrets
Enable App Configuration in Program.cs — Update the
CreateWebHostBuilder method to use App Configuration by calling the
config.AddAzureAppConfiguration() method.
#region Imports
using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureKeyVault;
using Microsoft.Extensions.Hosting;
#endregion
namespace AzureKeyVaultLabs.Web
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var settings = config.Build();
if (!context.HostingEnvironment.IsDevelopment())
{
var keyVaultEndpoint = settings["AzureKeyVaultEndpoint"];
if (!string.IsNullOrEmpty(keyVaultEndpoint))
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
config.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
}
}
}
}
For Azure Function Apps
public class Startup : FunctionsStartup
{
public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
{
if (builder != null)
{
//give your app configuration store endpoint
string connectionString = Environment.GetEnvironmentVariable("AppConfigurationConnectionString");
if (!string.IsNullOrEmpty(connectionString))
{
builder.ConfigurationBuilder.AddAzureAppConfiguration(connectionString);
}
var settings = builder.ConfigurationBuilder.Build();
var keyVaultEndpoint = settings["VaultName"];// Add key vault name in configuration
if (!string.IsNullOrEmpty(keyVaultEndpoint))
{
builder.ConfigurationBuilder
.SetBasePath(Environment.CurrentDirectory)
.AddAzureKeyVault(new Uri(keyVaultEndpoint), new DefaultAzureCredential())
.AddEnvironmentVariables()
.Build();
}
}
}
I want to get my Azure B2C AD access token from the httpContext or similar, but I am using .NET framework 4.7.2. If I was using .Net core, I would use HttpContext.Authentication.GetTokenAsync() .
Background
I am using OpenIdConnect 4.1.0.
My OpenIdConnectAuthenticationOptions looks like this:
private OpenIdConnectAuthenticationOptions CreateOptionsFromSiteConfig(B2CConfig config)
{
OpenIdConnectAuthenticationOptions options = new OpenIdConnectAuthenticationOptions();
options.MetadataAddress = string.Format(_aadInstance, _tenant, config.Policy);
options.AuthenticationType = [B2CAD-POLICY-name];
options.AuthenticationMode = AuthenticationMode.Passive;
options.RedirectUri = config.AzureReplyUri;
options.PostLogoutRedirectUri = config.LogoutRedirectUri;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "emails"
};
options.SaveTokens = true;
options.RedeemCode = true;
var identityProvider = GetIdentityProvider();
options.Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = AuthenticationFailed,
RedirectToIdentityProvider = notification =>
{
return Task.FromResult(notification.ProtocolMessage.UiLocales = config.UiLocale ?? string.Empty);
},
SecurityTokenValidated = notification =>
{
notification.AuthenticationTicket.Identity.AddClaim(new Claim("idp", "azureadb2c"));
// transform all claims
ClaimsIdentity identity = notification.AuthenticationTicket.Identity;
notification.AuthenticationTicket.Identity.ApplyClaimsTransformations(new TransformationContext(FederatedAuthenticationConfiguration, identityProvider));
return Task.CompletedTask;
},
};
options.ClientId = config.ClientId;
options.Scope = "openid [api-scope-here]";
options.ResponseType = "id_token token";
return options;
}
There is multiple policies with the same name (i.e. multiple AuthenticationTypes with same name).
So far, I have found several suggestions, where the most promising one suggested:
var result = await owinContext.Authentication.AuthenticateAsync([B2CAD-POLICY-name]));
string token = result.Properties.Dictionary["access_token"];
However, the result is always NULL, eventhough I have verified that the b2cad policy is actually present in the OwinContext.
Any help is much appreciated!