Skip to content

Commit fa186e7

Browse files
committed
Document auth/auth in README, remove obsolete TODO
1 parent c6f77cd commit fa186e7

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

README.md

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,53 @@ In addition, the following non-RESTful endpoints are implemented by
9090

9191
### Authentication and authorization
9292

93-
**TO DO**
93+
As noted above, authentication is somewhat tricky given that it runs
94+
on a different host from the GALC UI and browser makers have in the
95+
past few years cracked down hard on cross-site cookies. This makes
96+
Rails' traditional cookie-based session mechanism infeasible and
97+
requires us to rely on JSON Web Tokens.
98+
99+
Furthermore, CAS/CalNet has no provision for API-based authentication
100+
in the background; the only way to log into CalNet is to navigate to
101+
the CalNet login page.
102+
103+
The resulting authentication / authorization flow, then, is as follows:
104+
105+
1. User POSTs a form from the UI to the API's `/auth/calnet` endpoint
106+
(`login` in [`routes.rb`](config/routes.rb). The form includes a hidden
107+
`origin` field with the full UI URL to which the user should be
108+
redirected after login.
109+
2. The API `/auth/calnet` endpoint constructs a CalNet callback URL, consisting
110+
of the URL for the API `/auth/calnet/callback` endpoint plus a `url` query
111+
parameter capturing the `origin` value from the POST payload, and sends
112+
a `302 Found` response redirecting the browser to the CalNet login page,
113+
with the API callback URL (including the captured UI callback URL) as
114+
the value of a `service` query parameter.
115+
3. The user logs into CalNet, Duo, etc. and is redirected to the callback URL
116+
provided in the `service` parameter - the `/auth/calnet/callback` endpoint.
117+
4. The `/auth/calnet/callback` endpoint reads the user's identity and other
118+
relevant fields from the Omniauth / CalNet response, constructs a
119+
[`User`](app/models/user.rb) object, and serializes it as an encrypted JWT,
120+
then redirects the browser back to the UI, with the JWT appended to the
121+
UI callback URL as the `token` query parameter.
122+
5. Subsequent API calls made by the UI include the still-encrypted JWT in an
123+
`Authorization` header.
124+
125+
The UI can access relevant user information — name, email, privileges, etc. —
126+
by querying the `/users` endpoint while including that token, as mentioned above,
127+
but cannot itself decrypt / encrypt tokens.
128+
129+
Within the API application, the user information serialized and encrypted
130+
in the token is treated similarly to user information serialized in a
131+
traditional session cookie — certain endpoints require authentication,
132+
others require admin privileges, and so on.
133+
134+
**Note:** A key difference from the Library's monolithic Rails applications
135+
such as Framework, UC BEARS, and AV Player, is that unauthenticated API requests
136+
to endpoints that require authentication cannot simply be redirected to login.
137+
Instead they return `401 Unauthorized`, and it is the UI's responsibility to
138+
handle the situtation appropriately. In most other respects, GALC API
139+
authorization code is similar to those other apps.
94140

95141
### JSON serialization
96142

app/controllers/auth_controller.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ def index
1616
def callback
1717
logger.debug({ msg: 'Received omniauth callback', omniauth: auth_hash, params: params.to_unsafe_h })
1818

19-
# TODO: Store CalNet user in the session & compare token w/session
2019
user = User.from_omniauth(auth_hash)
2120
redirect_url = append_token(omniauth_origin, user.to_jwt_payload)
2221

0 commit comments

Comments
 (0)