Relation between rpc client (proxy) username and node Identity - corda

In Corda we are using CordaRPCClient to initiate transaction from the client. Here we are passing username and password to start the connection. Right now I am using hardcoded user name and password. Can I map this to a user table which is there in DB. Please share if there any best practices exists.

Yes you can definitely have rpc users fetched from a database. All you would need is some configuration in the nodes configuration file (node.conf).
The users are generally defined in the security block. Below is how it can be configured.
security = {
authService = {
dataSource = {
type = "DB"
passwordEncryption = "SHIRO_1_CRYPT"
connection = {
jdbcUrl = "<jdbc connection string>"
username = "<db username>"
password = "<db user password>"
driverClassName = "<JDBC driver>"
}
}
options = {
cache = {
expireAfterSecs = 120
maxEntries = 10000
}
}
}
You could find more details in our documentation here.

Related

Can we add users to keycloak in realms other than 'master'?

I can add users to keycloak but only in the master realm. Is there a way to add users to other realms beside master?
I tried and received an HTTP 401 Unauthorized Exception.
Sounds like your user doesn't have the manage-users role in other realms.
Just go to the admin realm, look up your user, navigate to Role mappings tab, then in the Client Roles drop down select the correct realm and then add manage-users as a role. Repeat for all realms.
//Here's how I created a user to my realm using Java
#Override
public UserDto registerNewUserAccount(final UserDto accountDto) {
String keycloakPassword = accountDto.getPassword();
accountDto.setPassword(passwordEncoder.encode(accountDto.getPassword()));
accountDto.setEnabled(1);
UserDto user = userRepository.save(accountDto);
AuthorityDto role = new AuthorityDto();
role.setUserName(accountDto.getLogin());
role.setAuthority("ROLE_USER");
authorityRepository.save(role);
Keycloak kc = Keycloak.getInstance(
"https://www.zdslogic.com/keycloak/auth", /your server
"zdslogic", //your realm
"richard.campion", //user
"Changit", //password
"admin-cli"); //client
CredentialRepresentation credential = new CredentialRepresentation();
credential.setType(CredentialRepresentation.PASSWORD);
credential.setValue(keycloakPassword);
UserRepresentation keycloakUser = new UserRepresentation();
keycloakUser.setUsername(accountDto.getLogin());
keycloakUser.setFirstName(accountDto.getFirstName());
keycloakUser.setLastName(accountDto.getLastName());
keycloakUser.setEmail(accountDto.getEmail());
keycloakUser.setCredentials(Arrays.asList(credential));
keycloakUser.setEnabled(true);
keycloakUser.setRealmRoles(Arrays.asList("user"));
// Get realm
RealmResource realmResource = kc.realm("zdslogic");
UsersResource usersRessource = realmResource.users();
// Create Keycloak user
Response result = null;
try {
result = usersRessource.create(keycloakUser);
} catch(Exception e) {
System.out.println(e);
}
if (result==null || result.getStatus() != 201) {
System.err.println("Couldn't create Keycloak user.");
}else{
System.out.println("Keycloak user created.... verify in keycloak!");
}
return user;
}

Identity Server: Access tokens/items set in AuthorizationProeperties in ExternalLoginCallback on the client

Question
I have an identity server implementation that is being used by a number of applications in test and production. I am currently working on a new feature, where the client application using the identity server can perform Azure service management REST api calls. For this, it needs a token. I can generate this token, store it and even access it in the AccountController in the identity server.
My issue is figuring out how to send this to the client. I don't think this token belongs in the claims for the user. So I tried to add it as part of AuthenticationProperties as a token, but I cannot seem to access it in the client. Should I store it in a session like this SO user did link? There is one answer to this question, but that does not seem right (I even tried it out of desperation!)
Relevant sections of code
Generate the token
var resource = "https://management.azure.com/";
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = async context =>
{
// Acquire the token for the resource and save it
}
}
}
Restore it in AccountController
public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
{
string resource = "https://management.azure.com/";
// snip
result = await authContext.AcquireTokenSilentAsync(resource, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
// snip
AuthenticationProperties props = null;
var tokens = new List<AuthenticationToken>();
var id_token = info.Properties.GetTokenValue("id_token");
if (id_token != null)
{
tokens.Add(new AuthenticationToken { Name = "id_token", Value = id_token });
}
if (result != null)
{
tokens.Add(new AuthenticationToken { Name = "management_token", Value = result.AccessToken });
}
if (tokens.Any())
{
props = new AuthenticationProperties();
props.StoreTokens(tokens);
}
// snip
// Can I access these "props" on the client? I even tried adding it to `Items`, no luck.
await HttpContext.Authentication.SignInAsync(user.UserId, user.DisplayName, provider, props, additionalClaims.ToArray());
}
So, my question, is this the right way go about it? If so, how do I access the authentication properties set? Or should I try saving this in the Session? If so, how do I store it in the client's session?
Any pointers would help. Thank you!
Just wanted to post an answer so that people wanting the same can benefit.
A token cache can be implemented to achieve this. This repository explains how.
Pay special attention to the AdalDistributedTokenCache linked here

Spring Security - ACL readAclsById not filtering by SIDs

I'm trying to use Spring Security's readAclsById method in JdbcMutableAclService to retrieve ACLs that are filtered by the SIDs. However, ACLs that are not applicable to the passed-in SIDs are returned.
I'm creating the ACL entry using the username:
public void add(Object domainObject, String username, List<Permission> permissions) {
MutableAcl acl;
ObjectIdentity oid = objectIdentityRetrievalStrategy
.getObjectIdentity(domainObject);
Sid receipient = new PrincipalSid(username);
try {
acl = (MutableAcl) aclService.readAclById(oid);
} catch (NotFoundException nfe) {
acl = aclService.createAcl(oid);
}
for(Permission permission:permissions) {
acl.insertAce(acl.getEntries().size(), permission, receipient, true);
}
aclService.updateAcl(acl);
}
And I'm retrieving ACLs via the Authentication object:
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
List<ObjectIdentity> identities = new ArrayList<>(domainObjects.size());
for (Object domainObject : domainObjects) {
identities.add(objectIdentityRetrievalStrategy.getObjectIdentity(domainObject));
}
Map<ObjectIdentity, Acl> acls = aclService.readAclsById(identities, sids);
//see what permissions the user has for these objects
for (Map.Entry<ObjectIdentity, Acl> entry : acls.entrySet()) {
Acl acl = entry.getValue();
//entries that are not applicable to the SIDs are returned
List<AccessControlEntry> entries = acl.getEntries();
}
If I log into another username and try to retrieve the ACLs via readAclsById, I also get AccessControlEntry values that belonged to the other usernames. Am I using AclService correctly?
I found the answer after some digging around the source code: the default implementation uses BasicLookupStrategy which ignores the SIDs by default.

ASP.NET authentication: adding similar part (domain) to all usernames

I am working on an authentication process for an ASP.NET web app. All my usernames follow the same template: login#domain.com. Domain is always the same.
My question is: Is there a way to add the part #domain.com automatically, so users could just type in their login in the username field?
Please, let me know if I need to provide some additional info to find the answer to this question.
Add domain name programmatically if it's not specified by users:
//var userNameWithDomain = "abc#domain.com" or "abc"; //get it from user's
//input
string[] arrUserName = userNameWithDomain.Split("#".ToCharArray());
string userName = null;
string domainName = null;
if (arrUserName.Length > 1)
{
userName = arrUserName[0];
domainName = arrUserName[1];
}
else
{
userName = userNameWithDomain;
domainName = "domain.com";
}

where to store user credentials in front end

in ASP.NET web API in the log in algorithm i have a action filter that generates a token for each user and the front end sends that token back to authenticate the user by using that token in web server i can get current user information till now every thing is working fine however i have new requirements that every user has relation many to many with account which means the same user can exists in more than one account with different roles for example in account one he is an admin in account two he is normal user so i have to regenerate the token which requires the user to re log in again i do not want him to be redirected to the log in page again. what i think of is to store user name and password in html 5 local storage but i think that is a bad practices any ideas.
Her is how i generate token.
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.Request.Headers
.Any(header => header.Key == "AuthorizationHeader"))
{
if (this.IsAnonymousAllowed(actionContext) == false)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Un Autherized");
}
}
else
{
string token = actionContext.Request.Headers
.Where(header => header.Key == "AuthorizationHeader")
.First().Value.First();
if (this.IsAnonymousAllowed(actionContext) == true)
{
return;
}
string passPhrase = System.Configuration.ConfigurationSettings.AppSettings["PassPhrase"];
string ticket_string = Crypto.Decrypt(token, passPhrase);
TicketData ticket = JsonConvert.DeserializeObject<TicketData>(ticket_string);
if (ticket == null || ticket.Expiration < DateTime.Now)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "UnAuthorized");
}
else
{
OurIdentity identity = (OurIdentity)ticket.TokenData.OurIdentity;
System.Threading.Thread.CurrentPrincipal = new OurPrincipal
{
OurIdentity = identity,
};
}
}
}
You are right saving username and password in the local storage is bad. It is bad to save it anywhere on the client.
Usually a token is generated and put in a cookie. That token corresponds with a record on the server, in either a session log or a database.
I strongly suggest to use existing methods for this, like OAUTH Bearer tokens in this tutorial.
As far as I understand, if you are storing a hash (perhaps with a salt for extra protection) it is not nessecescarily bad to store the credentials. These would have to be stored somewhere at the end of the day anyway.

Resources