subfission / cas

Simple CAS Authentication for Laravel 5 - 10.
MIT License
153 stars 72 forks source link

[Question] How about using an implementation with Laravel Guard? #90

Closed drupol closed 1 year ago

drupol commented 3 years ago

Hello,

I'm pretty new in the Laravel world and I'm learning how to use the Laravel Guards.

When I see this package, I'm wondering why the implementation is not using them. Is there a particular reason not to ?

Thanks!

subfission commented 3 years ago

This package is only an abstraction of the phpCAS tool. The implementation requires a Guard to be developed for the authorization portion of AAA. Everyone's CAS/SAML server responses may impact their applications in completely custom ways, so this was not added to this package.

Feel free to construct an example guard class and I will add it to the wiki for others.

orware commented 3 years ago

Would this issue be related to wanting to have a CAS user automatically added into Laravel's users table?

For most of the applications I work on there's a strong need for SSO (so either SAML or CAS, and I was able to use this package about 3 months back for an initial try out creating a Laravel application that authenticated using CAS, but I am wondering also if there is anything I might end up not being able to do due to their not being a true "user" record associated within the Laravel database down the road (and I wasn't sure if this issue/request was related to that same thing or not).

In particular, I feel the lack of an "id" value for a user within Laravel might cause an issue but not entirely sure. At the moment I could likely bring in an ID type value via CAS so that it's available as part of the attributes (and maybe use that in the future if I was storing data related to the user inside of new tables created within Laravel), but since I haven't actually done any of that just yet, I'm not 100% certain that it would all work as expected.

Thanks for putting the package together!

drupol commented 3 years ago

Would this issue be related to wanting to have a CAS user automatically added into Laravel's users table?

That could indeed be a solution.

I'm the maker of the Symfony counterpart of this package. I specifically opened this issue because I wanted to provide a package for Laravel that would be the same in terms of features, based on ecphp/cas-lib instead of apereo/phpcas

When I made ecphp/cas-lib, I really wanted to avoid manipulating the session within that library. The library should only be about authentication, nothing else. I think handling the session should be only made by the framework. In my packages, it is handled by ecphp/cas-bundle.

So, to come back to Laravel now. I started to create my own package before knowing that this one was existing. I started by creating a Guard and trying to replicate the same things as in Symfony guards.

After a week of trying, I gave up and opened this issue. Hoping that I could get some insights and clue on how to do it with a guard, without manipulating too much the session object.

orware commented 3 years ago

I'm still a relative Laravel newcomer as well, but not sure if the recent Fortify project might have useful tidbits: https://github.com/laravel/fortify

(It gets used underneath the hood by the other recent addition to Laravel called Jetstream: https://jetstream.laravel.com/2.x/introduction.html)

Since both are mostly written by the Laravel creator (and recent) they should be utilizing most of the current best practices available in Laravel 8.

drupol commented 3 years ago

I will most probably have a look this evening. I need to get through this :-)

subfission commented 3 years ago

Thanks for the insightful feedback. These questions really help with understanding the community needs.

I am not a deeply within Laravel these days since I have moved on to Python and other languages, but hopefully this is useful and addresses #92 as well.

This package was primary focused for use in higher education. When I built this originally, there were only 2 Laravel packages available for SSO. Both packages did not allow me the flexibility to implement my own designs for a user auth or use the advanced and nuanced capabilities of phpCAS. Additionally, the codebase for these were bloated with several features that did not improve the use of CAS. This project was developed to address that issue. Additionally, This project is weakly tied to Jasig phpCAS and can be modified to work with another CAS provider by editing 2 files. In practice, this package could be part of a suite that dynamically loads authentication providers, using this for just CAS/SAML It would be nice to see this attached to an LDAP package, for full dynamic authentication and authorization of a user.

Since breaking the code away from the original project and releasing this publicly, it has seen widespread adoption and downloads, across the globe. I have kept this project alive and moving forward, solely since there is still a community and interest.

In regards to SSO, this package does one process only, it queries your SSO provider and returns the response back to you for handling. This distinction is important as SSO is only used for authentication. The authorization aspect is where your custom code comes in to play.

Ideally you want your users to reside in a table, with preexisting permissions and roles. Perhaps you even have authenticated guests and or blacklisted accounts. None of this is mandatory of course, since you can choose your own strategy on how you determine user authorization.

Your middleware and auth guard provide the mechanism to determine whether a user has authorized access. This is where you will focus your efforts. Your custom class to be built eg. CustomAuthProvider will have a method public function validateCredentials(UserContract $user, array $credentials) that your middleware will use to establish authorization.

    public function validateCredentials(UserContract $user, array $credentials)
    {
        return ( !empty($credentials['a_student_id']) && $user->getAuthIdentifier() === $credentials['id']);
    }

Example PreCheck Authorization (post-CAS)

class AuthenticatePreCheck {

    protected $auth;

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if($this->auth->check()) return $next($request);

        // Get the account from the session if CAS succeeded
        if($student = ActiveStudent::askCASifAuthed())
        {
            if($user = $student->user)
            {
                $this->auth->attempt([
                    'id' => $user->id, 
                    'student_id' => $user->a_student_id
                ]);
            }
            return $next($request);
        }
        return abort(403);
    }