Authenticate a user based on a token and not through mysql table - jwt

round 2: trying to make this clearer:
I have two totally and completely separate services (both laravel 5.3).
One is an authentication service that has access to a user mysql database, permissions and role.
The other is a resource service. It couldn't care less about the user table and does not have access to any user table.
That means that any type of Auth::loginById()... would never work in this service because there is no user table.
I want to use JWT to have users access the resource service API, and have the user Auth to act as if a user is authenticated - but again - all I have are the claims inside the JWT - no user table. The claims include some information about the user - id, name, etc. I want to do something like this:
$userObj = JWTAuth::parseToken()->getPayload()->claims; // { id:4, name: Birdman, email: birdy414141#gmail.com}
Auth::login($userObj)
and then have access to the user object like usual
echo Auth::user()->name // Birdman
Has anyone tried anything like this?
I have found that doing this more or less works:
$u = new User();
$u->user_id = (JWTAuth::parseToken()->getPayload()->get('sub'));
$u->name = (JWTAuth::parseToken()->getPayload()->get('name'));
Obviously I can't $u->save() here because again - there is no user database.
I can do this though:
Auth::login($u);
and then I can later call Auth::user()->name properly...
I'm asking if I'm doing something exotic here or is this good stuff. Where will this fail?

Related

Where are Hasura roles stored?

I want to create authentication apis in Hasura. My user can have differrent roles when signing up. Thinking of maintaining an Enum table for the same. So that I can have a foreign key/type from it in the user table. However, I intend to create a postgress trigger on this enum table, such that everytime, new role is added, a new hasura role should also be created to allow for JWT authentication and authorization accordingly.
Where does hasura stores its Hasrua role.
Answer 1 (direct answer)
Not sure this is something the app developer should edit.
All Hasura metadata (including roles/permissions) is in Postgres.
The schema is "hdb_catalog". The table is "hdb_metadata".
You can query this using:
SELECT * FROM "hdb_catalog"."hdb_metadata" WHERE id = 1;
It contains a large JSON document. It's better to look at it using PGAdmin.
Answer 2 (dynamic roles)
It looks like you're trying to get dynamic roles in place.
There is a great Youtube video that explains how to model it:
https://youtu.be/-18zZO3DrLY?t=1370

Keycloak - Manage realm with user from different realm

Is possible to have user in one realm to manage another realm in keycloak?
My goal is to have 2 realms - adminRealm & userRalm. In adminRealm should be users, which will be able to log in to our admin app and there they could create via Keycloak rest api "ordinary user" which will be placed into userRealm.
Currently my solution working over one realm, where I have admin user which is able to log into my admin app and there he can create users in the same realm. But if I want create users to another realm, I get 403 error. So is there any way how to allow admin user to manage another realm (eg create users etc.)?
You should use master realm for storing admin accounts. Non master realms are isolated from each other. If you look to the clients list in master realm you should see that every realm represented by client with OIDC id like "foo-realm". This clients represents administration REST API for corresponding realms, and users with granted roles from this clients could perform admin requests to corresponding apis.
For example you have foo realm which will contain ordinary application users. To achieve your goal to introduce admin accounts that will be able to manage users from foo you have to create foo-admin user in master realm and grant him foo-realm.realm-admin role. Now this user has total control over foo realm and no control over master realm. You also can map foo-realm.realm-admin role to some group in master realm and add users to it (so if any changes appears in future you will have to change only group role settings)
In case you use terraform your solution would look like this:
data "keycloak_realm" "master" {
realm = "master"
}
data "keycloak_openid_client" "realm_management" {
realm_id = data.keycloak_realm.master.id
client_id = "foo-realm"
}
data "keycloak_role" "query_users" {
realm_id = data.keycloak_realm.master.id
client_id = data.keycloak_openid_client.realm_management.id
name = "query-users"
}
data "keycloak_role" "manage_users" {
realm_id = data.keycloak_realm.master.id
client_id = data.keycloak_openid_client.realm_management.id
name = "manage-users"
}
resource "keycloak_user_roles" "user_admin_roles" {
realm_id = data.keycloak_realm.master.id
user_id = keycloak_user.users_admin.id
role_ids = [
data.keycloak_role.query_users.id,
data.keycloak_role.manage_users.id,
]
}

Is there a way to setup a field-level authorisation on FaunaDB + GraphQL?

I'm having troubles finding a way to hide user emails from everyone, except the owner (user has access to only his email). Is there a way to hide a certain document field, for a certain roles?
Here is an example I found that creates a role with dynamic access to the whole User collection:
CreateRole({
name: "tier1_role",
membership: {
resource: Collection("User"),
predicate: Query(
Lambda("userRef",
// User attribute based rule:
// It grants access only if the User has TIER1 role.
// If so, further rules specified in the privileges
// section are applied next.
Equals(Select(["data", "role"], Get(Var("userRef"))), "TIER1")
)
)
},
privileges: [
{
// Note: 'allUsers' Index is used to retrieve the
// documents from the File collection. Therefore,
// read access to the Index is required here as well.
resource: Index("allUsers"),
actions: { read: true }
}
]
})
I tried to change it a bit, but I wasn't able to set up field-level access.
Let's say I'd set up FaunaDB with GraphQL schema below.
enum UserRole {
TIER1
}
type User {
email: String! #unique
username: String! #unique
role: UserRole!
}
type Query {
allUsers: [User!]
}
type Mutation {
addUsers(new_users: [UserInput]): [User]
#resolver(name: "add_users", paginated: false)
}
How do create a FaunaDB role in such a way that all of the users (except the current one) in resulting array from allUsers query, will not have email field?
I could break User collection into two: one is public, the other is accessible to a document owner, but this sounds wrong.
I'm new to the noSQL concept, so maybe I'm looking at this problem from the wrong perspective?
it's a request that came up a few times. You probably want to do this straight in FaunaDB's ABAC role system but although it provides row-level security, hiding a specific field is currently not provided yet. The feedback has been logged though, we will look into it.
The current way to do this is to split out Users from Accounts and fetch Users instead of Accounts. It would be useful to have something like hidden fields though in the future.
If you think of it, in this case, it does make sense to split authentication information from User information. You never know that you might offer another way to authentication in the future. I still recall from the Phoenix Framework book that they do it there was well and considered it a good practice.
You could also make a thin wrapper using Apollo in a serverless function and filter out these fields when you pass through the results. There is a guide that explains how to build such a thin Apollo middleware that just delegates to FaunaDB https://www.gatlin.io/blog/post/social-login-with-faunadb-and-auth0

Joins with Keycloak java admin client

I m trying to understand the admin client api of Keycloak, especially around joins.
There is this post that adresses a similar need for getting users per role.
Keycloak - Get all Users mapped to roles
How would we do this with the admin client?
Because for now I am retrieving all users and checking if the roles match:
List<UserRepresentation> userRepresentations = keycloak.realm(realm).users().search("", 0, 1000); //get all users :(
for (UserRepresentation userRepresentation : userRepresentations ) {
List<String> userRoles = userRepresentation.getRealmRoles();
if(userRoles != null && !Collections.disjoint(userRoles, roles)){
result.add(KeycloakUserTransformer.userRepresentationToSimpleUserDTO(userRepresentation));
}
}
And the thing is, userRoles list is always empty :S. But actually, we have ~2500 users in keycloak users.
EDIT:
I am using the keycloak admin client v.2.0. I guess the newer versions support this.
Thanks in advance.
With latest admin client you can easily get
RoleResource roleResource = keycloak.realm("realm_name").roles().get("role_name");
Set<UserRepresentation> users = roleResource.getRoleUserMembers();

Zend Navigation Multiple ACL roles

I am trying to create an ACL where users may have different roles in different departments.
The user is given a role in the form of role::guest or role::user depending if they are logged in. This is their userRole. (There is also a role::superuser that has access to all departments).
I have also added departmental roles to the ACL in the form of department::role (Eg. bookings::user). This is their departmentRole.
The users departmental roles are stored in the Zend_Auth identity.
The access control part works by extending Zend_Acl and over-riding the isAllowed function.
This successfully allows or denys each user.
public function isAllowed($role = null, $resource = null, $privilege = null)
{
$identity = Zend_Auth::getInstance()->getIdentity();
$userRole = $identity->role;
$departmentRoles = $identity->departmentRoles;
if (parent::isAllowed($userRole, $resource, $privilege))
{
return parent::isAllowed($userRole, $resource, $privilege);
}
else {
foreach ($departmentRoles as $departmentRole)
{
if(parent::isAllowed($departmentRole, $resource, $privilege))
{
return true;
}
}
}
return false;
}
The problem I am having is that Zend_Navigation requires an instance of the Acl and a single user role. My view script which builds the navigation menu uses $this->navigation()->accept($page) which only validates against the single user role.
How can I have multiple Acl roles for each user and have Zend_Navigation display menu items that they have access to?
If there is a better / different / correct approach to this please share.
Thanks
EDIT:
The fact that this approach meant over riding a core function in isAllowed() got me thinking this can't be the correct way to do this.
Now, in my ACL model I fetch all users, departments and associations and loop through creating an array for each user made up of their various roles within their relevant departments. I then create one role for each user and inherit the roles in the array previously created.
This is working well up to now and also means I can also add the users as resources and allow the relevant admin and department managers rights to amend their details etc.
It also means that I can pass a single role to Zend_Navigation and the menu structure should be relevant to their department roles.
IMHO having multiple ACL roles for single user looks like anti-pattern. Zend_Navigation rules are binded to (multiple) resources for single role which makes perferct sense.
What are your constraints that forbids you to allow resources for your (department) roles?
You can always use inheritance for your ACL roles.
If you prefer having multiple roles for single user, you might need to have separate ACL rules.
Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($acl);
Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole($role);