Open Luctum opened 1 year ago
@Taeir do you have thoughts on this? (No pressure; just asking you because you probably know more about SAML than anyone else on the team.)
Code wise it is relatively easy to do (we do it for my company too). Note however that the library that QPixel uses for SAML authentication only gives access to a single attribute value. So if your roles attribute contains multiple roles, only the first value is picked up.
This may or may not be a problem for your use case. For the used library there is an old issue (apokalipto/devise_saml_authenticatable#61) about it and even a pull request (apokalipto/devise_saml_authenticatable#159), but it's been open for years so it does not look like it is getting a lot of focus. Perhaps we can bump that a little?
In the file attribute-map.yml
map your roles attribute to saml_init_role
In the file app/models/concerns/saml_init.rb
add a method (ensure it is above the line that reads protected
)
def saml_init_role=(role)
case role
when 'COMPANY_GLOBAL_MODERATOR'
self.staff = true
self.is_global_moderator = true
when 'COMPANY_GLOBAL_ADMINISTRATOR'
self.staff = true
self.is_global_admin = true
when 'COMPANY_GLOBAL_DEVELOPER'
self.staff = true
self.developer = true
end
end
It is also possible to do more fine grained stuff like assigning specific privileges to users with specific roles, but this is separated per community and would only give privileges to the community being signed into. Let me know if you also need something for that.
As for adding this into QPixel by default, we could potentially have a saml_roles.yml
file and do simple mapping from there (e.g. you can specify global admin, global mod and just staff as options). Something like:
COMPANY_GLOBAL_ADMIN: global_admin
COMPANY_GLOBAL_MOD: global_mod
COMPANY_GLOBAL_STAFF: global_staff
This could then be processed by the saml_init_role method, which could look like (untested!)
def saml_init_role=(role)
roles = YAML.load_file(Rails.root.join('config/saml_roles.yml'))
case roles[role]
when 'global_admin'
self.is_global_administrator = true
self.staff = true
when 'global_mod'
self.is_global_mod = true
self.staff = true
when 'global_staff'
self.staff = true
end
end
(Though perhaps nicer to load the config only once and store it in the general configuration rather than upon every sign in request).
And if an organization already has SAML roles with different names, but the same single-role constraint already mentioned, using those roles would be a simple matter of locally editing the names in saml_roles.yml
, I presume? If this approach would meet the need that @Luctum describes, and if we can avoid loading it on every sign-in or for any deployment not using SAML, this sounds like a good addition to qpxel.
Hi !
Is your feature request related to a problem? Please describe. I'm currently setting up an autonomous qpixel instance. I would like to map roles to the admin and moderator roles already in QPixel. Currently I have to manualy setup role.
Describe the solution you'd like I would like to have a mapping for roles when connecting with SSO (ex: my XML returns an attribute "roles" with values like "COMPANY_GLOBAL_ADMINISTRATOR"). Note that the role name is tied to the company i'm working with, that's why I need to be able to use custom role values. This mapping could maybe be made in a separate yaml file or in attribute_map.yml for example
In my specific case, I only want to be able to map global administrators and global moderators automaticaly for specific users
Describe alternatives you've considered The only alternative I have right now is to remap every roles for every user manually. I tried to edit the saml_init.rb file but I could not manage to add the new property (I'm not really familiar with Ruby). Maybe if someone could explain me globaly how the mapping of the other attributes works in QPixel, I could try to implement this on my instance, test, and then make a pull request.