2021-02-25 CAS authN authZ conversations

Participants

@Steven Maglio
@Kevin Wu
@christian.montecino (Unlicensed)
@Vince Nievares

 

Email Summary

From: Kevin Wu <kevin.wu@ucsb.edu>
Sent: Thursday, February 25, 2021 4:18 PM
To: Steven Maglio <smaglio@ucsb.edu>; Christian Montecino <christianmontecino@ucsb.edu>; Vince Nievares <vince@ucsb.edu>
Subject: CAS authN authZ conversations

Hey all,

 Today was a GREAT meeting!  Learned a ton.  Some new things I've learned today:

  • There is a CAS Management page that we have access to such that we can pull levers and turn knobs:  cas-mgmt-t

  • There is an OAuth flow in CAS!  https://apereo.github.io/cas/5.2.x/installation/OAuth-OpenId-Authentication.html

    • From my understanding, client credentials is what we're after because this flow is for systems-to-systems communication.  All of the other flows require a human being to manually interact/push a button in order to allow for authorization to happen so those are non-starters.  In my head, client credentials flow is basically some account that is systems based being personified with a username and password.  It's like giving a username and password for your Roomba so your Roomba can invoke a notification service somewhere to communicate that it is currently vacuuming.

Ok, so putting all this together (inspired by Christian's example), we get this:

 

For the API Consumer, that translates to:

Request:

curl --location --request POST 'https://cas-t.identity.ucsb.edu/oauth2.0/accessToken?grant_type=client_credentials &client_id=seal-poc-test-oauth-1-cid&client_secret=4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4'

Response:

{     "access_token": "AT-2-pqKSL5oNt0AkQTBLsFsKUeLi9Ej37RbM",     "token_type": "bearer",     "expires_in": 28800,     "refresh_token": "RT-2-Edu37Sa1Q9Qj3LV9CqUzlJW1xG70Sy0y" }

 

So the API Consumer would perform this and get an access token.  The API Consumer then passes this access token to the resource server.  The resource server can't trust the access token, so it has to first verify the token before doing anything else:

Request:

curl --location --request GET 'https://cas-t.identity.ucsb.edu/oauth2.0/profile?access_token=AT-2-pqKSL5oNt0AkQTBLsFsKUeLi9Ej37RbM'

Response:

 Now the resource server can feel safe knowing that the access token belongs to seal-poc-test-oauth-1-cid because it reached out to CAS and CAS told it so.

 

THIS CONCLUDES AUTHENTICATION!  Everything up to this point was all about Authentication!

 

Now let's talk about Authorization.  This part is "easy" in the sense that the resource server has verified that this client seal-poc-test-oauth-1-cid says who they are.  It is now the resource server's responsibility to determine what authorization/roles this seal-poc-test-oauth-1-cid client has.  From here, you could really do anything you want.  Meaning, the resource server can simply lookup in its own system/database/resource and retrieve authorizations for this seal-poc-test-oauth-1-cid client and perform some action.

  • CAS OAuth Client Credentials -> Resource Server

In this case, the resource server would also contain logic needed to identify the authorizations for this client id before performing some action.

BUT verifying the CAS Access token and identifying the authorizations can also be performed as a separate middleware service prior to reaching the resource server... by delegating this authorization responsibility to some other service.

 

Alternatively, we can have a middleware service that performs the same CAS access token verification we did above, lookup in its own system/database/resource and then wrapping those claims in a JWT token.  Finally, the API Consumer can take the JWT token to the resource server where the resource server just verifies the JWT token because that's easy and super fast to validate.  JWT really shines here. (I'm not saying that CAS access tokens are not great). :)

  • CAS OAuth Client Credentials -> Authorization Middleware service -> Resource Server

In this case, the Resource Server has no smarts about authorization because it was done by our previous middleware service.  So as I'm writing and thinking about this, it's probably a bit cumbersome because the API Consumer would now need to track two things: 1) the CAS access token 2) the JWT claims tokens.  And both of these tokens can have their own expiration which needs to be managed by the Consumer.  I don't think this model is wrong, but well, we need authorization somewhere.  I guess what I'm trying to say is, we can either put the authorization inside the resource server or isolate authorization to be its own independent thing.  Maybe isolating it like this isn't ideal, but we can neatly box up the authorization middleware service and put that somewhere and not worry about it.  Somehow that idea fits better for me.  But happy to be convinced otherwise because maybe I need to look from a different angle.

 

THIS CONCLUDES AUTHORIZATION!  But wait!!  If you made it this far, OMG!

So this whole time, I've been experimenting with the seal-poc-test-oauth-1-cid client.  Now, what we talked about today is that it would be great if new apps created through the Developer Portal could AUTOMATICALLY create a new CAS service definition and that the service definition would use the client Id and client secret from the Consumer Key and Consumer Secret.

In this scenario, new API Consumer Apps automatically get created in CAS in preparation for the client credentials flow.  This would be great as it would solve the authentication problem in isolation.  But do we have any confidence that this is a possibility?  And in a reasonable timeframe?  I worry a bit about these types of integrations...

Do I have any of this right?  Help me understand if I took a wrong turn somewhere because writing this out was helpful to me and hopefully to others.

Thanks!

-Kevin