Custom flow - delegation - openiddict

I was wondering if it is possible to implement with openiddict a delegation grant type similar to the one implemented here with Identity Server.
var result = await _validator.ValidateAccessTokenAsync(userToken);
if (result.IsError)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
Is there any equivalent method to ValidateAccessTokenAsync in openiddict in order to validate the token and access some of its properties?

Implementation of standard token exchange is tracked by https://github.com/openiddict/openiddict-core/issues/1249.
In the meantime, you can override the default ValidateTokenParameter handler to work with your custom grant and extract the access token from the customer parameter you use:
https://github.com/openiddict/openiddict-core/blob/422d8979adb8cdebc6c8c8e14faa1d736208271e/src/OpenIddict.Server/OpenIddictServerHandlers.cs#L168
Then, you can call the IOpenIddictServerDispatcher.DispatchAsync() method with an instance of ProcessAuthenticationContext to trigger an authentication event. If IsRejected is true, this means the token is not valid. Otherwise, you'll be able to access its claims principal.

Related

Adding UserClaims During Startup.cs Seed Database

If a user signs in thru my GUI, all is well.
I use SignInManager to sign them in.
I create some claims.
I create a JwtSecurityToken with the claims attached.
I return JWT to client and they use it in header of future Http requests.
I have created a 'Provider' that accesses some of those claims on behalf of backend services. Those backend services are injected with the provider. When the service wants to know some info about the claim it asks the provider, which accesses the HttpContext, extracts claims and provides the requested value to the backend service. It works well.
My challenge is that I have now added a SeedData routine that is called during startup. It will create a user and then seed some business data (in the context of that new user).
The problem I have is that because this has not come from a client request, my HttpContext is NULL during SeedData routine called from startup.cs.
I have tried (within SeedData) to
// Sign in User
SignInResult signInResult = await signInManager.PasswordSignInAsync("username", "password", false, false);
// Create Claim
CustomClaim claim = new CustomClaim();
claim.ValueForBackend = "Foo";
// Add to Claims List
List<Claim> claims = new List<Claim>();
claims.Add(new Claim("custom-claim", JsonSerializer.Serialize(claim)));
// Create Claims Identity
ClaimsIdentity claimsId = new ClaimsIdentity(claims);
// Add the Claims Identity to current ClaimsPrincipal
HttpContextAccessor.HttpContext.User.AddIdentity(claimsId);
thinking that this would put the claims on the context so my provider can extract "Foo" when asked by the backend service.
However, I am getting error:
System.AggregateException: One or more errors occurred. (HttpContext must not be null.)
---> System.InvalidOperationException: HttpContext must not be null.
at Microsoft.AspNetCore.Identity.SignInManager`1.get_Context()
which appears to be thrown as soon as I try the initial sign in during start-up. My take-away from this is the there is not an HttpContext during startup.cs execution.
Is there a way during startup to:
Create initial user
Sign In as that user
Add some claims to that user
Perform seeding (calling backend services) in the context of that user
I could hack around it by creating a special provider of "Foo" that does not get the value from a claim, but is instead hard-fed directly from startup.cs, but wondered if there is a way to set up an HttpContext with claims during startup.cs.

Implement user authentication with gRPC

I'm looking to implement simple user authentication with my dart gRPC server + client and am struggling to find samples on how to achieve this properly.
So my problems are the following:
How do I add the user authentication data (JWT) to API calls that require authentication on the client?
How to I handle this data on the server?
I assume that on the client, metadata is the way to go, but is there a way to add the authentication data automatically for each call?
For the server, I assume that interceptors are the way to go, but how do I specify interceptors for specific services only (since not all API calls require authentication)?
is there a way to add the authentication data automatically for each call?
You can supply the default CallOptions with the options parameter in the generated client constructor.
You can use that to add authorization info to all your calls. If you need to perform async work for each call (for instance, to check if the token is still valid and optionally refresh it), you could add a MetadataProvider which gets invoked for each call.
how do I specify interceptors for specific services only (since not all API calls require authentication)?
The interceptor gets access to a ServiceMethod, which contains a name. So you could check that to only invoke an interceptor on some methods:
extension OnlyInterceptSome on Interceptor {
Interceptor limitTo(Set<String> endpoints) {
return (call, method) {
// Skip the check if we don't care about the method.
if (!endpoints.contains(method.name)) return null;
// Invoke the regular interceptor otherwise
return this(call, method);
};
}
}

Custom Auth request in ServiceStack for multi-tenancy

I am already using a custom authentication provider in my ServiceStack based web services application.
I'm overriding the Authenticate method, and validating my user against one of multiple backend tenant databases. I currently determine the tenant database by matching an API key to a database string.
public override object Authenticate(
IServiceBase authService,
IAuthSession session,
Auth request) // <- custom object here, MyCustomAuth request
{
// ...
}
This works when each application is for a single tenant (a tenant/customer can build their own application and use that API key). Moving forward I want to build a multi-tenant mobile application. Thus the API key method cannot be used because I can't expect each user to type it in, hence I can't determine which tenant is using the application.
I wanted to alter the Auth object so that I could include the TenantId (provided by the user on login). However, I can't see how I can customize that object.
Is there anyway to customize that Auth object, or do I have to find an alternative solution?
You can't modify the built-in Authenticate Request DTO used, but you can use its Dictionary<string, string> Meta property to send additional metadata with the Authenticate request, e.g:
client.Post(new Authenticate {
...
Meta = new Dictionary<string,string> {
{"TenantId", tenantId},
}
}
Alternatively you can send additional info in the QueryString or HTTP Headers and access the IRequest with:
var tenantId = authService.Request.QueryString["TenantId"];

How to get the userIdentity of the user being logged out when using Worklight adapter based authentication

I am currently implementing an adapter based authentication for my Worklight application.
For the record, I am using Worklight version 5.0.6.1.
What I would like to do is, as it seems to be advised in the documentation, to perform some cleanup in the "logout" function of my authentication adapter.
Thus, inside the logout function being called automatically by the Worklight framework, I'd like to retrieve the userIdentity object holding the info about the user being logged out. I tried to achieve this by calling "WL.Server.getActiveUser()", but it does not seem to be possible to do this in the logout function.
I can see the following exception in the logs (WebSphere App Server 7):
[9/3/13 17:13:11:683 IST] 00000039 DataAccessSer 1 com.worklight.integration.services.impl.DataAccessServiceImpl invokeProcedureInternal Procedure 'onLogout' invocation failed. Runtime: Adapter 'onLogout' security test has no user realm.java.lang.RuntimeException: Adapter 'onLogout' security test has no user realm.
The idea behind this is that I want to call an external REST service that will perform some cleanup in a DB, and I need the mobile application userId to be passed as a parameter of this service.
Could someone please give some best practices in order to retrieve the identity of the user being logged out from inside the authentication adapter logout function?
Thanks.
User identity is destroyed by an underlying auth framework before Adapter.onLogout() is invoked. As a result when Adapter.onLogout() is called the user identity doesn't exist any more. Therefore WL.Server.getActiveUser() will return null or throw exception (in your case because it doesn't have any user realm defined, which is perfectly fine).
In case you still require data from userIdentity even AFTER underlying auth framework discards it (and this IS your case) you can save userIdentity in session state. However you need to remember that since you're manually storing it there - it is also your responsibility to wipe it once it is not required anymore.
So the adapter code would be something like:
/* global var, not inside of any function*/
var userIdentity = null;
function submitCredentials(user, pass){
if (/*validate credentials*/){
/* using previously created global var, not declaring it again */
userIdentity = {
userId:user,
displayName:user
};
WL.Server.setActiveUser("realm", userIdentity);
}
}
function onLogout(){
/* do your stuff with userIdentity object and then wipe it*/
userIdentity = null;
}
The main difference with regular adapter flow is that userIdentity object is not created in the scope of a submitCredentials() function but as a global variable, therefore it is a session scoped var.

How to store custom information in SecurityContext of spring-security?

In my application I'm using LDAP authentication. But i'm also have 2 remote services which requires authentication via method login(username, password). The method returns security token which makes me able to invoke another methods, i.e. I should pass security token to service methods as first argument.
So I'd like to get these security tokens immediately after successful login using LDAP and store them in SecurityContext. I tried to use authentication-success-handler-ref of form-login element. Using the handler I replace Authentication object in the SecurityContext with custom AuthenticationToken that holds not only password but also security tokens. But in this case I have an exception that no authentication provider supports this class of token.
I know it's also possible to store tokens in the HTTP session but in this case I have to pass session to service object, so I'd like to store the tokens in SecurityContext.
What is the best approach to handle service security token?
I often use the Authentication.getDetails() object to store additional info that may not be directly linked to the user per say. So you can store any object you want in that field (a HashMap for instance) and it shares the Authentication object life cycle.
HashMap<String, Object> info = new HashMap<String, Object>();
info.put("extraInfo", "info");
auth.setDetails(info);
...
Map<String, Object> i = (Map<String, Object>)SecurityContextHolder.getContext().getAuthentication.getDetails();
Your implementation of 'UserDetails' may hold any additional data. This is what gets stored in the SecurityContext which is later accessible after successful login.
You can later access it as (Assumes MyUserDetails implements UserDetails)
Object principal = SecurityContextHolder.getContext().getAuthentication();
if (principal instanceof MyUserDetails) {
MyUserDetails mud = (MyUserDetails) principal;
mud.getMyData(); //Extract your additional data here
}