Vue is a lightweight, fast and awesome library for building user interfaces. Its learning curve is gentle and its API is not complex to understand. OAuth and OpenID Connect are standards-based protocols for identity and access management in applications. In this presentation, we will take an existing Vue application and implement authentication with OIDC, discover several idiomatic ways to integrate authentication, user profile consumption and conditional formatting with Vue as well as consuming a secure backend with OAuth.
7. auth0.com
Securing Vue.js with OIDC & OAuth
Cookies
and Server-side Web Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
8. auth0.com
Securing Vue.js with OIDC & OAuth / Cookies
Cookies and Server-side Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
9. auth0.com
Securing Vue.js with OIDC & OAuth / Cookies
Cookies and Server-side Apps
HTML/Data
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
10. auth0.com
Securing Vue.js with OIDC & OAuth / Cookies
Cookies and Server-side Apps
302
302
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
11. auth0.com
Securing Vue.js with OIDC & OAuth / Cookies
Cookies and Server-side Apps
HTML/Data
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
12. auth0.com
Securing Vue.js with OIDC & OAuth
Tokens
and Single Page Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
13. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
Tokens and Single Page Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
14. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
Tokens and Single Page Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
15. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
Tokens and Single Page Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
16. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
Tokens and Single Page Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
17. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
Tokens and Single Page Apps
JSON
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
18. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
” WHy nOt USe CookiES For
sIngLe pAGE APPS just LikE we
DO wITH TRAdiTiONaL WEb
Apps?"
Mocking SpongeBob, Jerkface
”Why not use cookies for single
page apps just like we do with
traditional web apps??"
Awesome SpongeBob, Smartie
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
19. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
Cross-Origin APIs
spongebob.io
mr-krabs.ru
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
20. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
”No problem! Everything I do is
on one domain!"
You (maybe), Theoretical Physicist
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
21. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
SPA + Backend on same domain
Cookie Considerations:
● Backend Authentication
● Authentication Redirects
● Ajax Calls
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
22. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
”I need to scale!”
”I have APIs on other domains!"
You (maybe), Theoretical Physicist
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
23. auth0.com
Securing Vue.js with OIDC & OAuth / Tokens
SPA + Cross Origin APIs*
* Now or in the future.
● Use Tokens!
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
25. auth0.com
Don’t store sensitive data
In Local Storage!
Securing Vue.js with OIDC & OAuth / Token Storage
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
26. auth0.com
Securing Vue.js with OIDC & OAuth / Token Storage
Local Storage Security Concerns
Steal data with XSS
https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
27. auth0.com
Securing Vue.js with OIDC & OAuth / Token Storage
Local Storage Security Concerns
Steal data with XSS Load malicious data with
XSS
https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
28. auth0.com
Securing Vue.js with OIDC & OAuth / Token Storage
Local Storage Security Concerns
Steal data with XSS Load malicious data with
XSS
Shared within an origin
https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
29. auth0.com
What should we do
instead?
Securing Vue.js with OIDC & OAuth / Token Storage
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
30. auth0.com
Securing Vue.js with OIDC & OAuth / Token Storage
Store Tokens in App Memory
you@authz-server
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
31. auth0.com
Securing Vue.js with OIDC & OAuth / Token Storage
Store Tokens in App Memory
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
32. auth0.com
Securing Vue.js with OIDC & OAuth
Guidance for Tokens
With Single Page
Applications
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
33. auth0.com
Securing Vue.js with OIDC & OAuth / Guidance for Tokens with Single Page Applications
Historically… *
* Since 2010
● OAuth Specification 2010
● OAuth 2 Specification 2012
● Angular 2012
● Vue.js 2014
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
34. auth0.com
Securing Vue.js with OIDC & OAuth / Historically…
Tokens Delivered via Browser Redirect
http://www...#
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
35. auth0.com
Securing Vue.js with OIDC & OAuth / Historically…
Token in URL Has Security Risks
http://www...#
● Redirect URI
● Browser History
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
36. auth0.com
Securing Vue.js with OIDC & OAuth / Historically…
Token in URL Has Security Risks
http://www...#
● Redirect URI
● Browser History
● Referrer Header
● Application Ignorance
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
37. auth0.com
Securing Vue.js with OIDC & OAuth / Historically…
We Mitigate These Security Risks
http://www...#
● Redirect URI
● Browser History
● Referrer Header
● Application Ignorance
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
38. auth0.com
Securing Vue.js with OIDC & OAuth
New Best Practices
drafted in 2019
https://tools.ietf.org/html/draft-parecki-oauth-browser-based-apps-02
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
39. auth0.com
Securing Vue.js with OIDC & OAuth / New Best Practices
Same Approach Used in Mobile Apps
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
40. auth0.com
Securing Vue.js with OIDC & OAuth / New Best Practices
Exchange a Code for a Token
code_verifier
code_challenge
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
41. auth0.com
Securing Vue.js with OIDC & OAuth / New Best Practices
Exchange a Code for a Token
code_verifier
code_challenge
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
42. auth0.com
Securing Vue.js with OIDC & OAuth / New Best Practices
Exchange a Code for a Token
code_verifier
code_challenge
code
http://www...#
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
43. auth0.com
code
Securing Vue.js with OIDC & OAuth / New Best Practices
Exchange a Code for a Token
code_verifier
code_challenge
http://www...#
code_challenge
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
44. auth0.com
Securing Vue.js with OIDC & OAuth / New Best Practices
Exchange a Code for a Token
code_challenge
code_challenge
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
45. auth0.com
Securing Vue.js with OIDC & OAuth / New Best Practices
Mitigations for Token in URL…
http://www...#
● Redirect URI
● Browser History
● Referrer Header
● Application Ignorance
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
46. auth0.com
Securing Vue.js with OIDC & OAuth / New Best Practices
…Not Necessary
● Redirect URI
● Browser History
● Referrer Header
● Application Ignorance
https://tools.ietf.org/html/draft-parecki-oauth-browser-based-apps-02
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
47. auth0.com
code
Securing Vue.js with OIDC & OAuth / New Best Practices
SDKs Can Do the Work For You
code_verifier
http://www...#
code_challenge
https://community.auth0.com/t/announcing-the-general-availability-of-the-auth0-spa-js-sdk/27399
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
48. auth0.com
Securing Vue.js with OIDC & OAuth
New Apps: New
Approach
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
49. auth0.com
Securing Vue.js with OIDC & OAuth
Existing Apps: No
New Threats
Courtesy of @KimMaida http://bit.ly/2019-music-city-code
51. auth0.com
Securing Vue.js with OIDC & OAuth / Checklist
Add an Authentication service
using dependency injection via
a plugin.
Restricting access to client side routes.
Handle Authentication events
like login and logout.
Conditional template formatting based
on Authentication status.
Displaying OIDC profile
information.
Sending Access Tokens with API
requests.
http://bit.ly/2019-music-city-code
61. auth0.com
Securing Vue.js with OIDC & OAuth / Bridging the Divide
Auth Service Reactivity
http://bit.ly/2019-music-city-code
62. auth0.com
Securing Vue.js with OIDC & OAuth / Checklist
Add an Authentication service
using dependency injection via
a plugin.
Restricting access to client side routes.
Handle Authentication events
like login and logout.
Conditional template formatting based
on Authentication status.
Displaying OIDC profile
information.
Sending Access Tokens with API
requests.
http://bit.ly/2019-music-city-code
68. auth0.com
Securing Vue.js with OIDC & OAuth / Checklist
Add an Authentication service
using dependency injection via
a plugin.
Restricting access to client side routes.
Handle Authentication events
like login and logout.
Conditional template formatting based
on Authentication status.
Displaying OIDC profile
information.
Sending Access Tokens with API
requests.
http://bit.ly/2019-music-city-code
70. auth0.com
Securing Vue.js with OIDC & OAuth / Authentication Events
Exposing Login and Logout to the User
http://bit.ly/2019-music-city-code
71. auth0.com
Securing Vue.js with OIDC & OAuth / Authentication Events
Exposing Login
and Logout to
the User
http://bit.ly/2019-music-city-code
72. auth0.com
Securing Vue.js with OIDC & OAuth / Checklist
Add an Authentication service
using dependency injection via
a plugin.
Restricting access to client side routes.
Handle Authentication events
like login and logout.
Conditional template formatting based
on Authentication status.
Displaying OIDC profile
information.
Sending Access Tokens with API
requests.
http://bit.ly/2019-music-city-code
75. auth0.com
Securing Vue.js with OIDC & OAuth / Checklist
Add an Authentication service
using dependency injection via
a plugin.
Restricting access to client side routes.
Handle Authentication events
like login and logout.
Conditional template formatting based
on Authentication status.
Displaying OIDC profile
information.
Sending Access Tokens with API
requests.
http://bit.ly/2019-music-city-code
78. auth0.com
Securing Vue.js with OIDC & OAuth / Checklist
Add an Authentication service
using dependency injection via
a plugin.
Restricting access to client side routes.
Handle Authentication events
like login and logout.
Conditional template formatting based
on Authentication status.
Displaying OIDC profile
information.
Sending Access Tokens with API
requests.
http://bit.ly/2019-music-city-code
80. auth0.com
Securing Vue.js with OIDC & OAuth / Secure API Requests
Including Access Token
With API Requests
http://bit.ly/2019-music-city-code
81. auth0.com
Securing Vue.js with OIDC & OAuth / Checklist
Add an Authentication service
using dependency injection via
a plugin.
Restricting access to client side routes.
Handle Authentication events
like login and logout.
Conditional template formatting based
on Authentication status.
Displaying OIDC profile
information.
Sending Access Tokens with API
requests.
http://bit.ly/2019-music-city-code
86. auth0.com
Title of the Presentation
This is a Big Title
This slide works as the introduction of a Chapter, Theme or
Section.
87. auth0.com
Title of the Presentation
auth0.com
This is a Big Title
This slide works as the introduction
of a Chapter, Theme or Section.
THIS IS A PLACEHOLDER.
YOU CAN PUT HERE AN IMAGE, GIF,,
DIAGRAM OR CHART
88. auth0.com
This is a Small Title for inner content
This is an extra small title
● Aspernatur aut odit aut fugit, sed quia consequuntur magni
● Ut enim ad minima veniam, quis nostrum exercitationem ullam
This is an extra small title
● Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
● Natus error sit voluptatem accusantium doloremque laudantium
Title of the Presentation / 1. Section A
89. auth0.com
This is a Small Title
Title of the Presentation / 1. Section A
This paragraph has highlighted
content, and it also has some bullets:
● Vestibulum ante
● Ipsum primis
○ Posuere cubilia
○ Aenean nulla enim
● Sed fermentum eget
THIS IS A PLACEHOLDER.
YOU CAN PUT HERE AN IMAGE, GIF,,
DIAGRAM OR CHART
90. auth0.com
Title of the Presentation / 1. Section A
Sansa Stark, Princess
@sansa-stark
Jon Snow, King
@jon-snow
Arya Stark, Princess
@arya-stark
This is a Small Title for inner content
91. auth0.com
Title of the Presentation / 1. Section A
Sansa Stark, Princess
@sansa-stark
Jon Snow, King
@jon-snow
Arya Stark, Princess
@arya-stark
Daenerys Targaryen, Queen
@daenerys-t
Tyrion Lannister, Prince
@t-lannister
Cersei Lannister, Queen
@cersei-queen
This is a Small Title for inner content
92. auth0.com
Title of the Presentation / 1. Section A
This is a Small Title Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
THIS IS A PLACEHOLDER.
YOU CAN PUT HERE AN IMAGE, GIF,,
DIAGRAM OR CHART
93. auth0.com
Title of the Presentation / 1. Section A
"The important thing is not to
stop questioning. Curiosity has
its own reason for existing."
Albert Einstein, Theoretical Physicist
95. auth0.com
Title of the Presentation / 1. Section A
Lorem ipsum dolor sit amet,
consectetur adipiscing elit
2K+
Lorem ipsum dolor sit amet,
consectetur adipiscing elit
42M+
Lorem ipsum dolor sit amet,
consectetur adipiscing elit
70+
96. auth0.com
Title of the Presentation / 1. Section A
2K+ Lorem ipsum dolor sit amet,
consectetur adipiscing 42M+ Lorem ipsum dolor sit amet, consectetur
adipiscing elit
Lorem ipsum dolor sit amet,
consectetur adipiscing
Lorem ipsum dolor sit amet, consectetur
adipiscing elit
Lorem ipsum dolor sit amet,
consectetur adipiscing elit
Lorem ipsum dolor sit amet, consectetur
adipiscing elit
97. auth0.com
This is a small title for inner content
Title of the Presentation / 1. Section A
100. auth0.com
Typography (Proxima Nova)
Resources
Color Palette
ELEMENTS
#EB5424
ELEMENTS
#0D96C6
Headline 1
Headline 2
Subtitle
Paragraph
Disclaimer
LINK
TEXT
#333333
TEXT
#666666
BG
#000000
BG
#333333
BG
#FFFFFF
TEXT
#CCCCCC
101. auth0.com
Icons
Resources
AUTH0 USER API RELATE CLI/SCRIPT APP MOBILE APP
SOCIAL
PROVIDERS
WEB APP
CREDENTIAL
USER
CREDENTIAL
APP
BACKEND ATTRIBUTES CERTIFICATION
BOUNDARY/
PROTOCOL
SERVER
GO TO GALLERY
105. auth0.com
Data Server Browser Mobile Laptop Login
Place in the icon to indicate status
ENABL
E
Title of the Presentation / Diagrams
This is the title of a Diagram
106. auth0.com
USERNAME SERVER BROWSER STATE A STATE B
Item #1
Description
Item #2
Description
Item #3
Description
Item #4
Description
Title of the Presentation / Diagrams
107. auth0.com
Title of the Presentation / Diagrams
Web AppToken Validator Layer
Token Cache
3 API 1
API 2
U1 Attributes
Imp: [U1,U2]
1
2
Notas do Editor
I am going to talk to you about authentication and authorization and vue.js based single page applications
If you were expecting another talk, you might be in the wrong place.
Few things about me:
I am a developer evangelist at an identity and access management company called Auth0
I run the Seattle Identity and Security and Auth0 Online Meetups
I am an avid Twitch streamer and member of the live coders team
I have been a software developer for around 20 years focused mainly on web development
And this is my dog Louie and I hanging out in the beautiful pacific northwest
I asked on twitter earlier this year, what are common reasons to roll your own authentication.
I got several very good reasons. Of course all of them are wrong.
Authentication is deceivingly simple.
you have a user who wants to access a resource.
If you look at this diagram, it looks easy, right?
The problem space we are talking about is extremely critical.
If something goes wrong, it goes catastrophically wrong.
Think 11.4 million euros level of catastrophe in the event of a breach.
This fact alone makes it one that requires a lot of attention.
Let’s start with talking about authentication in web applications.
By this I mean both traditional server side rendered web applications and single page applications.
Cookies are traditionally used with server side web apps
Built with frameworks like php, .net, java, nodejs
Those apps look something like this
{click}
You have your browser
{click}
And on the server you have your app and maybe a database
{click}
when the user submits their credentials to login
if it is successful
{click}
the server is going to set a cookie in the browser that represents the users session
the user is authenticated
the web app knows it and the browser knows it because it has a cookie
on subsequent requests to the server
{click}
the browser attaches the cookie to the request that is sent to the server
{click}
the server sends back the requested html and any sensitive data to the browser and the user can view it
if the cookie expires or there is no cookie and a requests made for protected data
{click}
the server will return a 302 redirect status, this will tell the browser to do a full page redirect to somewhere where the user can reauthenticate
{click}
once they have done that the application can send them secure data once again
in single page applications we typically see the use of token based authentication
this works a little bit different
We have a browser
{click}
and when the user navigates to our application
{click}
the app is compiled, downloaded and runs in the browser it's self
{click}
We usually get data from an API
{click}
not necessarily our own API. It could be but it could be someone else's as well.
we get tokens from something called an authorization server
{click}
which is a fancy term for a set of end points who's purpose is to issue tokens
the user submits their credentials to login to the authorization server
{click}
if everything checks out then the authorization server issues a token back
{click}
the token is then sent to our api with any requests for data
{click}
the api with verify the token with middleware
{click}
and if everything checks out on that end, data is returned as json which the app consumes
{click}
Here is a Question:
Why would we not just secure our single page app with cookies?
Just like we do with traditional web apps
{click}
This is actually a great question.
one reason is cookies only work on the domain of the application
{click}
so if everything is on the same domain then cookies will work for you
{click}
A lot of single page applications call APIs that live on other domains or they may need to in the future as the app grows.
{click}
If your API is on a different domain from your application that cookie is not going to work.
if you don't have this problem,
And your SPA + backend on the same domain:
You probably should consider securing your app with cookies.
Put the authentication layer in your backend because you own your backend.
{click}
But do authentication with routes served from the backend and then use cookies to secure the data that is moving between the single page application and the backend
{click}
one thing you do have to keep in mind though, if you do this. when an application uses a cookie based session in a traditional web app when the user tries to access a page, if they are not authenticated remember they get that 302 redirect status. And this is going to redirect the entire browser somewhere that the user can reauthenticate so that a cookie can be generated.
{click}
single page applications request data using ajax calls, so if your cookie is expired then the response is going to be a 302 redirect. in the single page application we need to add logic to handle that 302. We might be expecting a json response and we don't necessarily know what to do with an html page with a 302 on it.
you can handle that status and there is really no problem with doing this just be aware.
However, on the other hand if you know that you need to scale or you already have APIs that are on other domains
Then you are going to want to take the token based authentication approach.
so about tokens
a token is a very powerful artifact because the bearer of a token can access your secured data.
Historically it has been recommended that we store tokens in local storage.
But we actually should not do this because local storage has a distinct lack of data protection.
first of all any JavaScript running on the page has access to local storage.
So a cross site scripting attack if you have a malicious script or a compromised 3rd party script,
it can read the local storage object and steal all of it's contents;
any user info, any sensitive data, any tokens you put in there are basically up for grabs
if you are a victim of a XSS attack.
On the other side of that coin,
XSS can access local storage and push malicious data into it,
which can potentially make it somewhat untrustworthy of a source.
Finally all local storage is shared within a domain,
so if you have multiple applications running on the same domain all of those applications can access the same local storage object,
they could read each others tokens and things like that
if you had different authenticated apps on the same domain.
The most common reasons we put data in local storage is session persistence.
So that the user still has a token if they leave the application and come back.
We don't want to make them reauthenticate all the time, especially if they hit the refresh button.
What can we do instead of putting our tokens in local storage?
We want to store our sensitive data in application memory.
And when the user authenticates
{click}
Our authorization server the set of end points for issuing tokens can set a cookie in the browser that represents the user's session.
This cookie is not sent to the API or anything it is just the knowledge of what the users session state is with the authorization server itself.
So if we go and do something like refresh the browser
{click}
and lose all of our state, our app reloads and we dont have our token anymore.
{click}
But what we can do is use that cookie to check the session
{click}
and see if the users authorization server session is still valid.
{click}
If it is we can actually request new tokens silently without prompting the user for credentials
because the authorization server still knows about that user and has knowledge that they are logged in.
Having said said that here are some more guidance with using tokens for single page applications
This is a little bit of a history lesson here.
in 2012 when the oauth 2 spec was adopted single page apps were not main stream.
angularjs was born in this time frame but did not become popular until 2014.
vue.js was born in 2014 and took a couple years to really take off.
Both became relevant long after OAuth 2 was adopted.
Historically the guidance for doing authorization with browser based applications was to
{click}
deliver the token to the browser in a hash fragment of the url.
There is some inherent security risks with doing this.
The token is vulnerable in a number of places.
{click}
you have it in the redirect URL because you are redirecting the token to some URL that you are assuming is owned by the application. but if that redirect uri was hijacked then you could be sending your token to somewhere else.
{click}
in addition it is accessible in the browser history which is also accessible by JavaScript running on the page.
{click}
{click}
it is also potentially accessible in the Referrer Header, so if you are under attack and a malicious page is requested right after authentication takes place then the attacker can just look at the referrer header and take the token right out of it.
{click}
finally the app doesn't really know where the token is coming from. it just sees it in the url hash and it uses it. so it does not necessarily have a way to verify if it is coming from a trusted source. or if it was injected maliciously from somewhere else.
Authorization servers and app developers who implement authentication actively work to mitigate these risks right now.
So the mitigation guidance has been around for 7ish years.
There are no new threats to this approach so these same mitigations are going to continue to work.
There are no new vulnerabilities that have found their way around these mitigation strategies.
But as modern JavaScript and web applications evolve we reevaluate and recommend new practices.
it's time to have our recommendations be a little bit more secure.
The approach we are recommending now from the IETF is the same approach used in mobile applications already.
So it is not exactly a new approach. But it is new to the world of browser based apps.
In this scenario we basically exchange a code for a token.
And that works something like this.
I'm going to go over this a little bit quickly.
Don't worry to much about it.
{click}
The first thing we need to do in our application is create a random string called a code verifier.
This is a high entropy random string.
{click}
Next we are going to compute another random string from the verifier using a hashing method that gives you something called a code challenge.
Now when the user logs in
{click}
the credentials and the code challenge are sent to the authorization server.
The server then returns a code
{click}
which is received by the browser in a hash fragment.
And this is fine because interception of this code isn't dangerous.
The code by itself cant be used for anything.
It cant grant somebody access if they were to steal it.
Once we have the code we take the code and the code verifier and send them to the authorization server.
{click}
Now what we can do is we can recalculate the code challenge from the verifier
{click}
and then we want to make sure the challenges match the one that was sent by the app earlier and the one we just generated.
If the challenges match
{click}
then a token is issued as a json object and sent to the application and it can consume it.
Now all the mitigations for the risks that I talked about earlier with having the token in the URL
we don't need those anymore if we used this other approach.
This seems like kind of a lot. It is several steps to take.
There's hashing methods involved and exchange a code bla bla bla.
{click}
But don't worry about this to much because SDKs can handle this for you.
Ultimately if you are building a new application and you need to add authentication to it
then you should probably consider using this new approach.
It's more secure, and fewer mitigations.
But if you have existing applications that use the token in the URL approach
as long as you are mitigating the risks that I talked about there are no new threats you need to worry about.
You don't need to run out and freak out about all of a sudden my apps not secure anymore.
It is just as secure as when you built it.
That brings us to the second half of this talk,
How to implement secure vue.js applications.
How do we take a generic authentication specification and weave it into a vue application?
Let’s start with a bit of a checklist of what we are going to be covering
{click}
We will add a global authentication service via a dependency injection plugin {click}
We restrict client side routing based on authentication status {click}
We then handle authentication events like logout and login. {click}
Look at conditional template formatting based on authentication status. {click}
Consume the authenticated users openid connect profile {click}
Sending an access token with api requests
Authentication is a cross cutting concern.
Different portions of our apps will need to interact with it in different ways.
Vue.js offers two ways to handle cross cutting concerns
Mixins are a flexible way to share functionality across Vue components.
You simply create an object that defines the shared methods.
And then declare the mix in as part of your component definition.
But this is not really what we are looking to do exactly.
Plugins on the other hand add global level functionality to Vue.
Plugins on the other hand add global level functionality to Vue.
You are probably already familiar with using plugins
Both VueRouter and Vuex install as plugins.
Here is a common example of adding axios as a global http request handler
making it available to any component that needs it.
This makes plugging in our auth service pretty clean
In this example our main.js imports the plugin
and tells Vue to use it passing along the configuration values needed
Since we are delegating authentication to an OIDC based identity provider
We pass along the identity providers domain
And the client id we received when we registered our client with that provider
Since the provider is also handing our OAuth based authorization as well
We pass in the specific audience we are concerned with.
Finally, a bit of magic telling the service how to handle the callback redirection.
Now you maybe thinking, hey wait a minute where is this authentication service coming from?
There is a whole bunch of math and fanciness involved that I am hiding under that ”createService” call.
If you recall earlier, I said that you didn’t need to be too concerned with generating or parsing cryptographic keys.
And that is because SDKs can handle that for you.
At a low level I am taking advantage of an SDK that we released recently
which was designed specifically for single page applications
that wish to use the Authorization Code Grant Flow with PKCE
I described earlier.
The service is simply a thin wrapper over this SDK that makes it behave in a Vue like fashion.
This brings us to another nifty feature of Vue, it’s reactivity model
We are all probably familiar with vue’s reactivity in a component defined like this.
We start out defining a data element named foo with a template bound to the value bar.
When the mounted method executes it changes the foo value to baz
And Vue’s reactivity will automatically update the template value to match.
That reactivity is not limited to our UI components
We can leverage it any where we like.
The auth service implementation is simply another reactive vue component
That wraps the sdk exposing a set of reactive properties and methods we can consume
From any component
This particular example handles the complex redirect callback logic described earlier
Then fetches the user profile
and notifies anyone that cares that user is authenticated.
This will come in handy later.
There is more to the service that we will see soon,
but you can check out the source of a fully functional app on your own.
And with that we have injected a reactive authentication service
Packaged up nicely as a vue plugin.
Now that we have a reactive auth service we can leverage it
to handle restricting access to client side routes defined in VueRouter.
VueRouter is pretty easy to use and in common practice now.
Out of the box it offers several ways to make decisions about route navigation
In this example we have two of the most common forms of route guards.
A global, defined on the router itself that effects all routes of a given router.
And a per-route guard, that is applied directly to the route definition.
The function signature is the same for both:
You are given the route that we are navigating to
The route we are navigating from
And a next method that we can use to allow or redirect the navigation.
So with that in mind it is pretty trivial to implement a guard that takes our auth service into account
This guard will allow navigation if the user is authenticated
Or redirect them to our authorization server to login
One thing to note here is that we pass some appstate along with the request
That lets our application know where to send the user back to once they have successfully authenticated.
Back in our router we simply apply the guard to any routes we wish to require authentication.
In this example I am applying it directly to a specific route.
We could use it globally, but we would need to make sure to exclude any public routes from consideration.
And with that we have restricted client side routes based on authentication.
With all that done how do we actually let the user login and out of our application?
This is surprisingly simple.
With our login service exposed as a global service
we literally just define methods to call the relevant methods.
Here our login method delegates login to the loginWithRedirect method
that directs the browser to the identity provider for authentication.
The log out method simply makes a call to the identity provider to end the session
And routes the user to the root of the application
With the methods exposed, we simply call them via the click directive in our UI elements.
And with that we have handled the authentication events and hit the half way mark in our list.
The are times when we would like to show or hide elements in our app based on the authentication state of the user.
Because the auth service is setup to be reactive and is exposed to all components.
Conditional formatting is pretty trivial.
We can use the if directive to ask the service directly.
If the user is not authenticated, show the login button
If the user is, show the logout button.
When the reactive values change the UI updates accordingly.
Note we are also checking with the service to determine if it is in a loading state.
There is a brief period of time where the service calls the identity provider to get details needed to validate tokens,
So we want to make sure the service is ready before proceeding.
Bam that was the fastest one yet
When the user is logged in we want to give them some indication that is the case.
This is also fairly simple thanks to the reactivity.
Here we used a computed property to return a user profile if it is available
Or default values if it is not.
When the user becomes available it will be swapped in.
We are reaching the finish line here…
If you recall, when we configured the user service,
We supplied an audience value, we could have also specified any oauth scopes we wanted as well.
The net effect of doing this is that we are issued an access token at the same time we received our OIDC based id token.
Here the component loads its own data when mounted.
We simply ask the auth service for the token
And make the request using a http request service setting the headers appropriately.
This might look a bit different if you are using a flux light library like Vuex, but you get the idea.
One thing to point out here, notice the service method is called get token silently.
This is a nice feature of the underlying SDK we are using. It will check to see if the token we currently have is expired
And silently request a new one from the authorization server if needed.
Very nice.
And with that we have completed our whirlwind tour of securing a vue app with Open ID connect and OAuth.
OK how much time do I have left?
Would you rather I open it up for question or do a quick demo?
So all of the examples in this presentation were pulled from a real application
The source is up on github and you can find a link to it via the bit.ly link at the bottom of every slide presented.
Let’s take a quick look at the application.
Thank you for your time. If you would like to keep up with me, you can find me in these places.
Once again you can find all the presentation materials at this bitly link including source of the demo application.
I want to give a special thanks to Kim Maida who graciously allowed me to borrow some of her theory explanations and diagrams.
Thanks!