Getting the Latest Code
The project is available here and can be be downloaded / cloned to your local PC with this command:
- git clone https://github.com/garyarcher36/authguidance.websample2
How to Run the Improved Sample
The only difference to the Setup Instructions for the previous code sample, is to run ‘npm install’ and ‘npm start’ from new folder locations in steps 8-10:
Updated Component Interaction
The code sample now interacts with an API that uses Central User Data, and we use API Claims Caching, so our architecture now looks like this:
Which Business Domain?
APIs used by Corporate Apps might return data related to Medical Data, Pensions or Stocks and Shares, with Complex Business Rules.
Most online OAuth blogs use personal data, such as Photos or Contacts, which are secured very differently to Corporate Assets.
I want this blog’s Code Samples to feel a little like they were operating on Sensitive Corporate Financial Assets.
Our business theme will be Startup Funding from small investors. The UI will be trivially simple but aims to represents data that needs protecting.
Our API will return hard coded information on ‘pretend startups’ to our UI. We will imagine that this monetary information is Confidential and that users might have Different Permissions to Different Assets.
We can drill into details for each startup to see a few ‘pretend investments’, which will again be hard coded. Obviously a real system would offer much better views for analysis and decision making.
Login and Bookmarked Locations
The main reason for the 2 views is to demonstrate user friendly navigation within our SPA. A user can bookmark the Transactions View for a particular startup they are interested in, then close their browser.
When the bookmark is next clicked the user will be prompted to login but will then be restored to the page they bookmarked – this is sometimes called Deep Linking.
You can simulate deep linking by clicking Expire Token and then Refresh Data – to see how the user is redirected back to the same location.
Technical User Navigation
Our SPA uses REST-ful URLs so the user can quickly see investments for another startup by editing the Startup Id in the browser address:
Note that in a Corporate App the user may not have permissions to the Startup with id 2, so the software will need to handle this, and should also cope elegantly with the user typing ids that do not exist.
API Claims Handling
The Improved API uses the Claims Handling mechanism we described earlier, to look up User Info and then cache it, mapped to the hash of the Access Token.
If we run the API with ‘npm run httpDebug’, we see that, when a token is first received, the API makes calls to Introspect the token and to get User Info:
The API could use these claims to apply business rules, and the API caches claims in memory before returning:
On subsequent API calls, the claims are quickly looked up from the memory cache, so all calls after the first are much faster:
UI Claims Handling
Although the UI doesn’t understand the access token, the UI calls the API operation at /userclaims/current and can get whatever user data it needs.
In our sample this is a little contrived of course, because we do not have any complex user data.
Our Claims Implementation
We have made these choices for the Code Sample’s implementation:
- The API gets Central User Info from the Okta User Info Endpoint
- The API does not use any Product Specific User Data yet
- The UI gets User Data from its API rather than from Okta
Different choices may work better for your scenario, but the key goal is an extensible setup that you can easily change later.
Errors as Entities
As discussed in an earlier post, there is plenty of scope for configuration / connectivity / infra failures when you start using OAuth technologies.
I always recommend treating errors as (technical) entities, in the same manner as we treat business data as entities.
- First we will re-run the case where our UI supplied an invalid scope – to show the UI receiving an error from the Authorization Server:
- Next we will show an example of an API error, when is being run with ‘npm run httpDebug‘ but cannot connect to the Introspection Endpoint due to Fiddler not running:
We also follow security best practice, by ensuring that the API logs full technical error details, but only returns limited details to the UI:
Errors Ids for Fast Lookup of Details
Note that in the above screenshots each instance of an error has an id field that can easily be communicated to your support staff by end users, either over the phone or via email.
For my real world apps I always ensure that error occurrences are stored in a server side database. This enables you to quickly look up details and also to measure the number of occurrences over time.
Errors Handling and Productivity
In my experience it is worth taking the time to do the above things early during the development process:
- Design the UI fields you will want to display when problems happen
- Treat errors as objects / entities containing those fields
- Test failure scenarios early, to get this work out of the way
Once done you will have a more productive developer setup. Also it will give you a better chance of resolving any production issues quickly, and this can help improve your company reputation.
Where Are We?
Both our UI and API have been updated to a RESTful, high performance and extensible design. We have also made some reliability improvements.
We are still not using Open Id Connect in the recommended way, and we do not have proper Session Management features for End Users.