I am currently developing a Silverlight 3 app that needs some sort of user authentication, because the data pulled from a WCF service is user specific. Target audience is the regular Internet - so there is no AD to authenticate against.
Here are some of the questions I have concerning that situation:
Is there a framework or other mechanism that would support me?
Would you recommend authentication within the Silverlight app or via outside mechanisms like forms auth? Which is more secure?
What about out-of-browser support?
I used ASP.NET's authentication. Just use a MembershipProvider (or implement your own).
Then go to http://www.silverlightshow.net/items/Accessing-the-ASP.NET-Authentication-Profile-and-Role-Service-in-Silverlight.aspx to check out how you can expose the authentication service.
Then in your WCF service, you do the following (hosted in ASP):
public class MyWCFService : IMyWCFService
{
// retrieve your UserId from the MembershipProvider
private int GetUserId()
{
MembershipUser user = Membership.GetUser();
int userId = (int)user.ProviderUserKey;
return userId;
}
// check if user is authenticated
private bool IsUserAuthenticated()
{
return HttpContext.Current.User.Identity.IsAuthenticated;
}
public void Subscribe()
{
if (!IsUserAuthenticated())
{
throw new SecurityException("You must be authenticated to be able to use this service.");
}
int userId = GetUserId();
DoStuff(userId);
}
}
Hope that helps.
I would consider using the the authentication classes that exist in ASP.NET. You can then use .NET RIA Services (or even simply, WCF) to communicate with authentication service.
Consider this article as a primer.
Related
Are there any examples of using itfoxtec-identity-saml2 with asp.net core Identity.
Specifically, I have many SAML Idps (https://stubidp.sustainsys.com, Okta, Auth0, Salesforce, etc) and I want to add them using AuthenticationBuilder.
public static class Saml2Extensions
{
public static AuthenticationBuilder AddSaml(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<Saml2Options> configureOptions)
{
...
}
}
A good example would have a mix in of Google, Azure both using OIDC, and a few SAML ones.
I'm afraid that I do not have sutch an example. I always put a proxy / broker IdP in between, in my case I use FoxIDs. That way the application only need to know about one IdP and would then ask the broker IdP to handle the up-stream IdP authentication.
I have an ASP.NET 6.0 Web API project. I would like to add authentication and authorization to it, but it must use SSO via Azure.
We already have a SPA application that does this, it uses the Angular MSAL library to redirect the user to an SSO Login page, then returns to the SPA with an access token. The access token is then added to the header of each request to the Web API, which uses it to enforce authentication.
Now we want to share our web API with other teams within our organization, and we would like to have that login process just be another API call, rather than a web page.
Conceptually, a client would hit the /login endpoint of our API, passing in a userID and password. The web API would then get an access token from Azure, then return it as the payload of the login request. It's then up to the client to add that token to subsequent request headers.
I have done this with regular ASP.NET Identity, where all of the user and role data is stored in a SQL database, but since our organization uses SSO via Azure Active Directory, we would rather use that.
I have researched this topic online, and so far all of the examples I have seen use a separate SPA, just like we already have. But as this is a web api, not a front-end, we need to have an API method that does this instead.
Is this even possible? I know Microsoft would rather not have user credentials flow through our own web server, where a dishonest programmer might store them for later misuse. I understand that. But I'm not sure there's a way around this.
Thanks.
I believe you are looking for the Resource Owner Password (ROP) flow. You can use IdentityModel.OidcClient to implement it.
Sample code:
public class Program
{
static async Task Main()
{
// call this in your /login endpoint and return the access token to the client
var response = await RequestTokenAsync("bob", "bob");
if (!response.IsError)
{
var accessToken = response.AccessToken;
Console.WriteLine(accessToken);
}
}
static async Task<TokenResponse> RequestTokenAsync(string userName, string password)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(Constants.Authority);
if (disco.IsError) throw new Exception(disco.Error);
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "roclient",
ClientSecret = "secret",
UserName = userName,
Password = password,
Scope = "resource1.scope1 resource2.scope1",
Parameters =
{
{ "acr_values", "tenant:custom_account_store1 foo bar quux" }
}
});
if (response.IsError) throw new Exception(response.Error);
return response;
}
}
Sample taken from IdentityServer4 repository where you can find more ROP flow client examples.
I would recommend that you don't go with this implementation and instead have all clients obtain their access tokens directly from Azure AD like you did with your Angular SPA.
We have two separate dotnet core apis(API1 & API2) that are protected using azure ad b2c. Both these apis are registered on the b2c tenant and have their scopes exposed. We have a client web application that is to access the above protected apis. This web app has been registered in b2c tenant and has api permissions set for the above apis with proper scopes exposed.
In a previous post about what's the best approach to configure the web app so that it is able to access multiple protected apis, an approach was suggested to "Combine both services into a single app registration and expose different scopes."
While trying to implement that, I am also to validate the scopes present in the access token along with the audience and authority.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtOptions =>
{
//validating the access token with client id and token issuer(authority)
jwtOptions.Authority = Configuration["AzureAdB2C:Authority"];
jwtOptions.Audience = Configuration["AzureAdB2C:ClientId"];
});
services.AddMvc();
services.AddMemoryCache();
services.AddControllers();
// Start Registering and Initializing AutoMapper
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
// End Registering and Initializing AutoMappe
}
How best to validate the scopes of access token?
Any help is appreciated.
This article from Auth0 has a really nice tutorial of how to create a custom Authorize attribute that grabs the scope claim ("scp") off the token and validates the scope for each controller method. This can certainly be done more globally if you only have 1 scope per service. https://auth0.com/docs/quickstart/backend/aspnet-core-webapi/01-authorization
I have been looking over examples of using Asp.Net Identity and various providers to supply authentication using facebook, twitter, etc.
I have an MVC 6 solution, currently being developed using VS2015 RC. It will be deployed to an organisational IIS. AD is primarily used to authenticate users, the majority of whom are authenticated via the domain, either within the local network or remotely.
However there is the possibility that some users will want access to the system over the internet, without having a domain account. or these users, the user will register, an admin will approve the account and assign roles and permissions locally within the application database.
The project team are requesting that users on the local network or otherwise authenticated on the domain do not need to logon.
AD is in use, but not ADFS to the best of my knowledge.
Is this even possible? I believe what I need is an OWIN provider for AD, but the Microsoft one seems to work with either ADFS or AAD.
Thanks.
You can definitely use Asp.Net Identity for the users that are registering over the internet.
You can also use Asp.Net Identity to sign-in the AD users using the below nuget package, but the windows users information (just the username, email) will need to be stored in your application database.
https://github.com/MohammadYounes/OWIN-MixedAuth
After you implement this nuget package, just do this to authenticate the windows user.
Add this method in ApplicationSignInManager class in IdentityConfig file and call this method if the windows user is logging in.
public async Task<SignInStatus> WindowsLoginAsync(string userName, string password, bool isPersistent)
{
var signInStatus = SignInStatus.Failure;
using (var context = new PrincipalContext(ContextType.Domain, <your_domain_name>))
{
var valid = context.ValidateCredentials(userName, password);
if (valid)
{
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(context, userName);
if (userPrincipal != null)
{
var loginInfo = new ExternalLoginInfo
{
Login = new UserLoginInfo("Windows", userPrincipal.Sid.ToString())
};
signInStatus = await ExternalSignInAsync(loginInfo, isPersistent);
return signInStatus;
}
}
}
return signInStatus;
}
This will basically use cookie authentication for windows and web users alike.
After the user is authenticated you will need to add the windows user in the database and also add a record in IdentityUserLogin table with LoginProvider as "Windows" and ProviderKey as the userPrincipal.Sid and then call SignInManager.SignInAsync to login the user.
Using this approach I believe the windows user can also login over the internet, which your organization might not like.
Hope this helps!
I am working on a Messaging Application built using WPF and WCF-RESTful site.
This application is used inside intranet as well as internet. The application prompts for authentication (custom login screen in the messaging application) when it accessed through internet (outside the domain).
We have written authentication logic in the WCF service like below:
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
{
if (!pc.ValidateCredentials(userName, password, ContextOptions.Negotiate))
{
return string.Empty;
}
}
The Website's application pool is set to use NetworkService. The website's authentication is "Anonymous" as the Intranet User's do not require to authenticate.
I do not get any error or exception. Instead, it always returns "false" for any username even though the credential are correct.
Can you please tell me what I am missing here?
Take a look here http://travisspencer.com/blog/2009/07/creating-users-that-work-with.html plus if userName is in format domain\userName try to parse it from the domain name and send only the user part as argument to ValidateCredentials