Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra attributes #163

Open
aderouineau opened this issue Jan 27, 2013 · 9 comments
Open

Extra attributes #163

aderouineau opened this issue Jan 27, 2013 · 9 comments
Labels

Comments

@aderouineau
Copy link

It would be great if the implementation could provide a fixed extra attribute for an authenticator. It would be a way for services to know what kind of user it is depending on how it was authenticated.

Also, an extra attribute mapper would be welcome. With this feature, a service can get the good attribute even if SQL and LDAP have different "columns".

@mitfik
Copy link
Contributor

mitfik commented Jan 30, 2013

I think we have something like that, please take a look here:
https://github.com/rubycas/rubycas-server/blob/master/config/config.example.yml#L180

also check other authenticators for extra_attributes.

@aderouineau
Copy link
Author

As I understand it, the feature provided is to give extra attributes from the backend but not fixed values.
What I am looking for is a way to send values set in the configuration itself, that are independent of the user being authenticated.

Consider the following case :
Take a small and a large organization that are independent. The small one has an Active Directory, and the large one has LDAP. The small one wants to provide a CAS server for its services that could be used by users from both organizations. The CAS server will first try to authenticate with Active Directory, then LDAP.
The small organization wants to provide special sub-services to its own users. The way to do that would be for the CAS server to set an extra attribute with a value of "internal" or "external" for example.

The way to do that would be for rubycas-server to allow setting fixed attributes per-backend in the configuration:

authenticator:
class: CASServer::Authenticators::ActiveDirectoryLDAP
[...]
fixed_attribute: type, internal

authenticator:
class: CASServer::Authenticators::ActiveDirectoryLDAP
[...]
fixed_attribute: type, external

@aderouineau
Copy link
Author

As for the second point, if one does this :

  extra_attributes: full_name

The key of the extra attributes will be set to "full_name".

If you use another authenticator that has another column/property for the full name, how can the service handle those attributes independently from the authenticator used?

@mitfik
Copy link
Contributor

mitfik commented Feb 1, 2013

extra_attributes is per authenticator, you can have different extra_attributes for different authenticators.

Just to clarify, because I am not sure if I understand what you trying to achieve.

One CAS server for both organization (A and B).
Organization A wants to launch new service but access only for user from A.
Organization B should not have possibility to log in to this service.

Is that correct?
If yes, I think right now there is no good solution for that, but after implementing oauth between apps and cas we could have it. I will add that to the wish list.

@aderouineau
Copy link
Author

No, it is not really correct. Based on the example I gave in my last reply,

The first authenticator sends out a fixed extra attribute of key "type" and value "internal".
The second authenticator sends out a fixed extra attribute of key "type" and value "external".

Then the services can determine whether to allow people or not. Remember, CAS is about authentication, not so much authorization.

These attributes are static because they do not depend on the user; they are attached to the authenticator.
As of now, an extra attribute is necessarily attached to the user but there are uses of having authenticator-wide attributes rather than per-user attributes.


Do you understand both of my requests now?

@mitfik
Copy link
Contributor

mitfik commented Feb 6, 2013

hmm as I understand that it is exactly this what I mean.
Maybe I explained it in a wrong way but it seems to be exactly the same scenario.
So you want that this service which will communicate with cas deiced what to do base on that which authenticator will pass through. It can be done by send back fixed_value as you suggest or by sending back id of authenticator which verified the user. Then service will check which authenticator handle the authentication and decide what to do.
Because you do not need any special value there you just need to distinguish which authenticator was used to authorize the user. So I will suggest to add just id field for each authenticator for example:

authenticator:
  - class: CASServer::Authenticators::Google
     id: 1
  - class: CASServer::Authenticators::SQL
     id: 2
    database:
      adapter: mysql
      .
      .
      .

and CAS will send back this id of authenticato which was used to the service.
This id could be also used as parameter which will force particular service to authorize users base only on one authenticator or group of them if there is more.
For example service ask to authorize user and pass through information that he want just to use 1 authenticator not all of them.

What do you think about this functionality it will solve all your issues?

@slowjack2k
Copy link

I think what you wan't can be easaly achiefed by yourself. You "only" have to create custom authenticators
derived from the Authenticator you wan't.

It can look like this (only dirty example)

class MySQLAuth < CASServer::Authenticators::SQL

  def extra_attributes
     merged = @extra_attributes.dup  
     # fixed_attributes:
     #         - name: type
     #           value: internal 
     @options["fixed_attributes"].each do |int_attr|
         key = int_attr["type"] # you need to change 
        value = int_attr["value"]
        merged[key] = value
      end

     merged
  end
end

@aderouineau
Copy link
Author

@mitfik What I described is an example scenario. But I'm sure there are other cases that could benefit from fixed attributes that your solution wouldn't satisfy.

@slowjack2k That's an interesting idea. Why not implement something like that at the authenticator parent class? I think that's basically what I'm requesting actually :)

@slowjack2k
Copy link

I think your request with static attributes is very special in my opinion. I don't know how many user's would use this feature. So i think a custom adapter would be a better solution.

But I missed your second feature request and there i think your right. It would be nice if not the application has to decide what's the name of an extra attribute. For instance with sql-adapter the extra attribute is company and
with ldap company_name.

I would extend Authenticators::Base

  def extra_attributes
     if  extra_attributes_mapping_needed?
       mapped_extra_attributes(@extra_attributes)
     else
        @extra_attributes
     end
  end

  def mapped_extra_attributes(attrs)
    new_attrs ={}
    #ToDo handle special attrs not mentionen in config file
    @options[:extra_attributes].each do |old_name, mapped_name|
        new_attrs[ mapped_name]=attrs[old_name]
    end
     new_attrs
  end

 def extra_attributes_mapping_needed?
    @options[:extra_attributes].kind_of? Hash # or better use an option map_extra_attrs with true false
 end

 def extra_attributes_to_extract
        if @options[:extra_attributes].kind_of? Array
          attrs = @options[:extra_attributes]
        if @options[:extra_attributes].kind_of? Hash
          attrs = @options[:extra_attributes].keys
        elsif @options[:extra_attributes].kind_of? String
          attrs = @options[:extra_attributes].split(',').collect{|col| col.strip}
        else
          $LOG.error("Can't figure out attribute list from #{@options[:extra_attributes].inspect}. This must be an Array of column names or a comma-separated list.")
          attrs = []
        end

        $LOG.debug("#{self.class.name} will try to extract the following extra_attributes: #{attrs.inspect}")
        return attrs
      end

so it would be possible to define extra attributes this way

  extra_attributes:
         name_in_the_adapter: name_the_app_needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants