Been looking into the identity server 4 solution to compliment my ASP CORE api.
Using a SPA page on front end, does IdentityServer4 have the capability to manage restfull calls for login/logout/other?
Currently my solution works perfectly to redirect to and from the IdentityServer4 solution, but wondering if i can improve on UX by avoiding the redirects that occur on login/logout?
I've heard of PopUp and iFrame capability, but from research that opens up other risks.
(not sure if this question is for stackoverflow or software engineering stack, happy to move it)
You may do this by using the resource owner password grant type, where you could provide your own login screen and pass the information to IdentityServer.
In IdentityServer you would implement the IResourceOwnerPasswordValidator interface to validate the users.
In your Startup.ConfigureServices add the following.
Services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
Here is a sample ResourceOwnerPasswordValidator class.
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
private IUserManager _myUserManager { get; set; }
public ResourceOwnerPasswordValidator(IUserManager userManager)
{
_myUserManager = userManager;
}
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
var user = await _myUserManager.Find(context.UserName, context.Password);
if (user != null)
{
context.Result = new GrantValidationResult(
subject: user.USER_ID,
authenticationMethod: "custom",
claims: await _myUserManager.GetClaimsAsync(user));
}
else
{
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidRequest,
errorDescription: "UserName or Password Incorrect.");
}
}
}
The IUserManager implements the logic to check the database to validate the user.
Then the SPA client would use the GrantTypes.ResourceOwnerPassword. Here is an example you could start with.
DISCLAIMER
This is not the recommended flow to use.
What is the best way to manage a user session in a Google App Engine application? Ideally I'd like to keep my application stateless and not save any user related data in memory, however I'm also afraid to send user credentials of the network on every request (not to mention authenticating the user on every request would require a call to the Datastore which costs money).
I checked out google's OAuth 2.0 solution but from my understanding it helps if my application wants to connect to any of the google APIs and needs permission from the client to access his google account.
Is there a go to way for managing user session? The most common scenario is to know which user initiated this request without having to send the userId as a request parameter.
Please note that we are not using third party providers. The user registers himself to our page normally and has a custom account. I'm not looking for tools that help integrate authentication with third party services. Otherwise I'd be using google's OAuth 2.0 or similar API
You can Always implement Authenticator Interface.
public class MyAuthenticator implements Authenticator {
#Override
public User authenticate(HttpServletRequest request) {
HttpSession session = request.getSession(false);
//
return null;// if not authenticated, otherwise return User object.
}
}
// Endpoints class.
#Api(name = "example", authenticators = { MyAuthenticator.class })
public class MyEndpoints {
public Profile getProfile(User user) {
if (user == null) {
throw new UnauthorizedException("Authorization required");
}
return new Profile(user.getEmail(), "displayName");
}
// store this class somewhere in models
public class Profile {
private String email;
private String displayName;
public Profile(String email, String displayName) {
this.email = email;
this.displayName = displayName;
}
public String getEmail() {
return email;
}
public String getdisplayName() {
return displayName;
}
}
}
Use the HttpServletRequest object to implement classic session based login or use your own custom header. Well that depends on your case. Return null when not authenticated and return User object when authenticated. Also implement some kind of encryption on both sides(client and server), so as to stop someone having the session key to access your api.
Note: Cross-posted to ServerFault, based on comments.
Intro
I need to password protect some actions in my application, such as loading/saving files, clicking check-boxes, etc. This is a standard C# .Net 4.0, WinForms application which will run on Windows 7 in a corporate network.
I was about to roll my own very basic system (read obfuscation with wide open backdoors) with a text file of users/passwords/permissions (hashed and salted) until after some searching I found what looks like a
tantalizingly simple approach , but I'm having trouble finding a good tutorial on Roles that isn't about ASP.NET.
Question
So does anyone know of one or more tutorials that show me how to:
Create a Windows User/Group and give that User/Group a Role or Permission.
Note that I'm testing this from my company's networked laptop, but will deploy it on the customer's corporate network (Not sure if this is an issue, or how tricky this will get).
Create winforms/console app sample with even just a single method that prints "Hello World" if I'm authenticated or throws an exception if I'm not?
I've never done Network Admin or anything related and I keep reading about Active Directory and Local Users Vs Networked Users... I was hoping for an approach where I could build to an Interface and just ask Windows if the current user has permission ABC and not care too much about how Windows figured that out. Then I can make a concrete implementation for each Local/Network/ActiveDirectory/etc. use case as required (or if required... as I don't even know that right now).
Background
- read if interested, but not required to answer question
Just to make sure I'm going in the right direction here, basically I need/want to test this on my development PC to make sure it's going to have a good end-user experience for my customer. The problem is that currently they run an Auto-login script for each computer that runs my application and there are several different operators that use my application throughout the day. The customer wants password protection on certain features of my app and only provide that to certain operators. I have no problem fitting this in, as I've expected the request for a while, I just haven't ever programmed authentication before.
I think it's worthwhile to convince my customer to give each operator their own network account and assign whatever permissions they want to that operator or group, in case they need to fire somebody, change permissions, etc. It also means I just open several options for them and they can group those permissions however they see fit based on internal corporate policies, which I really shouldn't have to be worried about (but will be if I have to roll my own, as they're IT department knows almost nothing of my application).
From what I can tell it also makes my life a lot easier by not having to deal with hashing passwords and encryption, etc. and just handle which Role is required to click this or that button.
First of all, you'd have to determine, if you really want a simple role-based-authentication (you may want to read: http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/)
If you're sure it's absolutely sufficient, you're already on the right way with the SO link you provided in your question. It's kind of confusing that there is no support of 'roles' by default in Windows, but there are groups. Groups can be local or remote (e.g. ActiveDirectory), so an admin could assign users to certain groups, that are specific for your application (for an example look here: http://msdn.microsoft.com/en-us/library/ms731200(v=vs.110).aspx)
One key is: You have to prepare your application's central principal, hence fill it with roles, supported for the current user.
Therefore, On the very startup of your application you then check the current active user and set your application wide principal and role(s). This may look like this (just a very simple example):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Principal;
using System.Text;
using System.Threading;
namespace WindowsPrincipalTrial
{
public class Program
{
// you could also move these definitions to a config file
private static IDictionary<string, string> _groupRoleMappings = new Dictionary<string, string>()
{
{"MYAPPUSERGRP", MyRoles.Standard},
{"MYAPPSUPPORTGRP", MyRoles.Extended},
{"MYAPPADMINGRP", MyRoles.Admin},
};
private static void Main(string[] args)
{
var windowsId = WindowsIdentity.GetCurrent();
if (windowsId != null)
{
var allRoleNames = getGroupCorrespondingRoles(windowsId);
var newPrincipal = new GenericPrincipal(windowsId, allRoleNames);
Thread.CurrentPrincipal = newPrincipal;
}
else
{
throw new NotSupportedException("There must be a logged on Windows User.");
}
}
private static string[] getGroupCorrespondingRoles(WindowsIdentity id)
{
// you also could do this more elegant with LINQ
var allMappedRoleNames = new List<string>();
string roleName;
foreach (var grp in id.Groups)
{
var groupName = grp.Translate(typeof(NTAccount)).Value.ToUpper();
if (_groupRoleMappings.TryGetValue(groupName, out roleName))
{
allMappedRoleNames.Add(roleName);
}
}
return allMappedRoleNames.ToArray();
}
}
public static class MyRoles
{
public const string Standard = "standard_role";
public const string Extended = "extended_role";
public const string Admin = "admin_role";
}
}
Then your Application-Principal is set up.
Now you could check access in your code like this:
public void DoSomethingSpecial()
{
if (Thread.CurrentPrincipal.IsInRole(MyRoles.Extended))
{
// do your stuff
}
else
{
// maybe display an error
}
}
Or more drastically:
public void DoSomethingCritical()
{
var adminPermission = new PrincipalPermission(null, MyRoles.Admin);
adminPermission.Demand();
// do stuff
}
what is possible even declarative, as known from ASP.NET:
[PrincipalPermission(SecurityAction.Demand, Role=MyRoles.Admin)]
public void DoSomethingMoreCritical()
{
// do stuff
}
The ugly thing with the latter two examples is, that they throw exceptions, when the right role isn't hit.
So the mapping between roles and groups you have to do quite at the start of your app, according to the systems you want to use (local groups, AD groups, LDAP groups etc.).
If you, however, prefer authentication with actions and roles, after all, have a look at Windows Identity Foundation and Claims Based Authorization! There are already some ready-to-use frameworks out there (e.g. https://github.com/thinktecture/Thinktecture.IdentityModel).
UPDATE:
When it comes to activity based and thereby claims based authorization, I will try in short, how you could achieve it, by using Thinktecture's IdentityModel.
Generally that approach still uses roles internally, but has a kind of translation layer in between. Thinktecture already encapsulates many things needed. Authorization checks in code are then done via claim permissions. They are technically kind of request for an access to a certain resource. For the sake of simplicity I limit my example for actions only, by using one single default resource (since ClaimPermission doesn't accept an empty resource).
If you want to use action#resource pairs, you'd have to modify the code respectively.
At first you need a ClaimsAuthorizationManager
public class MyClaimsAuthorizationManager : ClaimsAuthorizationManager
{
private IActivityRoleMapper _actionToRolesMapper;
public MyClaimsAuthorizationManager(IActivityRoleMapper mapper)
{
_actionToRolesMapper = mapper;
}
public override bool CheckAccess(AuthorizationContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
try
{
var action = getActionNameFromAuthorizationContext(context);
var sufficientRoles = _actionToRolesMapper.GetRolesForAction(action)
.Select(roleName => roleName.ToUpper());
var principal = context.Principal;
return CheckAccessInternal(sufficientRoles, principal);
}
catch (Exception ex)
{
return false;
}
}
protected virtual bool CheckAccessInternal(IEnumerable<string> roleNamesInUpperCase, IClaimsPrincipal principal)
{
var result = principal.Identities.Any(identity =>
identity.Claims
.Where(claim => claim.ClaimType.Equals(identity.RoleClaimType))
.Select(roleClaim => roleClaim.Value.ToUpper())
.Any(roleName => roleNamesInUpperCase.Contains(roleName)));
return result;
}
// I'm ignoring resources here, modify this, if you need'em
private string getActionNameFromAuthorizationContext(AuthorizationContext context)
{
return context.Action
.Where(claim => claim.ClaimType.Equals(ClaimPermission.ActionType))
.Select(claim => claim.Value)
.FirstOrDefault();
}
}
As you may have guessed, IActivityRoleMapper is an interface for a class, that returns the names of all roles, that include permission for a given action.
This class is very individual and I guess you'll find your way implementing it, because it's not the point here. You could do it by hardcoding, loading from xml or from a database. Also you would have to change/extend it, if you wanted to you action#resource pairs for permission requests.
Then you'd have to change the code in main() method to:
using Thinktecture.IdentityModel;
using Thinktecture.IdentityModel.Claims;
using Microsoft.IdentityModel.Web;
private static void Main(string[] args)
{
var windowsId = WindowsIdentity.GetCurrent();
if (windowsId != null)
{
var rolesAsClaims = getGroupCorrespondingRoles(windowsId)
.Select(role => new Claim(ClaimTypes.Role, role))
.ToList();
// just if you want, remember the username
rolesAsClaims.Add(new Claim(ClaimTypes.Name, windowsId.Name));
var newId = new ClaimsIdentity(rolesAsClaims, null, ClaimTypes.Name, ClaimTypes.Role);
var newPrincipal = new ClaimsPrincipal(new ClaimsIdentity[] { newId });
AppDomain.CurrentDomain.SetThreadPrincipal(newPrincipal);
var roleMapper = new ActivityRoleMapper(); // you have to implement
// register your own authorization manager, so IdentityModel will use it per default
FederatedAuthentication.ServiceConfiguration.ClaimsAuthorizationManager = new MyClaimsAuthorizationManager(roleMapper);
}
else
{
throw new NotSupportedException("There must be a logged on Windows User.");
}
}
Finally you can check access this way:
public const string EmptyResource = "myapplication";
public void DoSomethingRestricted()
{
if (!ClaimPermission.CheckAccess("something_restricted", EmptyResource))
{
// error here
}
else
{
// do your really phat stuff here
}
}
Or again, with exceptions:
private static ClaimPermission RestrictedActionPermission = new ClaimPermission(EmptyResource, "something_restricted");
public void DoSomethingRestrictedDemand()
{
RestrictedActionPermission.Demand();
// play up, from here!
}
Declarative:
[ClaimPermission(SecurityAction.Demand, Operation = "something_restricted", Resource = EmptyResource)]
public void DoSomethingRestrictedDemand2()
{
// dostuff
}
Hope this helps.
I've been able to find lots of stuff about using the ASP .NET Membership provider in WPF. I've even got the ASP .NET Role provider working in my WPF application. These are very easy to use in WPF. What I can't find any information about is how to use the ASP .NET PROFILE provider in a WPF application.
My application will be running on a laptop located in a moving vehicle; it cannot use Web Services to connect to a server and authenticate the user. My code needs to be able to retrieve the user's profile information from the local database.
I've tried several times to build a class that derives from ProfileBase but nothing I've tried has worked. To elaborate, the code below is an excerpt from my latest failed attempt:
public class UserProfile : ProfileBase {
[CustomProviderData( "AlarmsToDisplay;int" )]
public int AlarmsToDisplay {
get { return (int) GetPropertyValue( "AlarmsToDisplay" ); }
set { SetPropertyValue( "AlarmsToDisplay", value ); }
}
// Other properties following the same pattern follow.
private UserProfile() { }
public static UserProfile GetUserProfile( string username ) {
return Create( username ) as UserProfile;
}
public static UserProfile GetUserProfile( string username, bool isAuthenticated ) {
return Create( username, isAuthenticated ) as UserProfile;
}
}
In this code, the method GetUserProfile( string username, bool isAuthenticated ) returns null. I believe this is because the compiler can't cast a ProfileBase to a UserProfile, even though UserProfile descends from ProfileBase. Please correct me if I'm wrong.
Can someone point me to an existing article or describe the proper way to build a user profile class that extends from ProfileBase?
I've managed to resolve this issue on my own. Here's what works:
Remove the attributes from all of the CLR properties. These do not work with the default aspnet_Profiles table.
In app.Config, you need to add an "inherits" attribute to the tag. This has to be set to the fully qualified name of your class, separated from the assembly file name (no extension) by a comma.
Once these things were done, the GetUserProfile method and the ProfileBase class's Create methods return UserProfile objects.
I am trying to add to the authentication system provided in the Silverlight 4 business template as my model does not completely fit that provided in the template. I have an existing web service that performs my authentication and provides roles and also permitted operations for each role. This is the model provided by AzMan/Authentication Manager.
However, rather than just get a single role, following authentication I provide the user with a list of available roles and allow the user to select one of these roles and then get a list of operations/actions for that selected role.
The problem that I have is that I can't work out how to add new methods to the authenticationservice to allow me to get the operations for the current user, and currently selected role in order to complete the login process e.g.
public SessionInfo GetOperations(string username, string selectedRole)
{
SessionInfo sessionInfo;
using (AzManServiceClient azClient = new AzManServiceClient("AnonymousAuthentication"))
{
sessionInfo = azClient.LoginUserByUsername("msldap://CN=LiveApps,CN=Program Data,DC=HLSUK,DC=local", "AIRS", selectedRole, null, username);
}
return sessionInfo;
}
The above method is not accessible from the LoginForm.xaml.cs using WebContextBase.Current.Authentication... Only methods such as Login are visible which is even more baffling because I can't see these methods in authenticationbase. I'm completely confused. How do I add new methods to the authentication service, or should I create a new domainservice, or should I access the azman service to get the operations directly from the silverlight client.
Have you tried to Override the methods in AuthenticationBase?
Then you can expand your authenticationservice with whatever logic you want.
<EnableClientAccess()>
Public Class AuthenticationRiaService
Inherits AuthenticationBase(Of UserAccount)
Protected Overrides Function ValidateUser(ByVal userName As String, ByVal password As String) As Boolean
End Function
End Class
Also set
WebContext.Current.Authentication To your authenticationservice as found in namespace System.ServiceModel.DomainServices.Client.ApplicationServices
Sorry for stupid VB code. :D