|
1 | 1 | # AngularJS OAuth2 |
2 | 2 |
|
3 | | -This is a bower plugin for adding OAuth 2 authentication support to AngularJS. |
| 3 | +This is an Angular directive and HTTP interceptor available as a Bower package for adding OAuth 2 authentication support to AngularJS. In addition to this documentation a couple of samples and tutorials are available: |
| 4 | + |
| 5 | +[Authenticating AngularJS Against OAuth 2.0 / OpenID Connect](http://www.azurefromthetrenches.com/authenticating-angularjs-against-oauth-2-0-openid-connect/) |
| 6 | +[Sample of IdentityServer3 and AngularJS-OAuth2](https://github.com/JamesRandall/AngularJS-OAuth2-IdentityServer3-Sample) |
| 7 | + |
| 8 | +The package is versioned using the [semantic versioning policy](http://semver.org). |
| 9 | + |
| 10 | +Feedback is very welcome. Please leave it in the [Issues](https://github.com/JamesRandall/AngularJS-OAuth2/issues) area or over on my [blog](https://www.azurefromthetrenches.com). |
| 11 | + |
| 12 | +## Installing the Package |
| 13 | + |
| 14 | +Use the Bower package manager to install the package into your AngularJS project: |
| 15 | + |
| 16 | + bower install --save angularjs-oauth2 |
| 17 | + |
| 18 | +## Basic Usage |
| 19 | + |
| 20 | +To authenticate an application running on localhost using Google's OAuth2 endpoint add the following HTML to, typically, your index.html page: |
| 21 | + |
| 22 | + <oauth2 authorization-url="https://accounts.google.com/o/oauth2/auth" |
| 23 | + sign-out-url="https://accounts.google.com/o/oauth2/revoke?token=" |
| 24 | + sign-out-append-token="true" |
| 25 | + client-id="*** get a client ID from the Google Developer Console ***" |
| 26 | + redirect-url="http://localhost" |
| 27 | + response-type="token" |
| 28 | + scope="openid"> |
| 29 | + </oauth2> |
| 30 | + |
| 31 | +However the plugin is fully compatible with any Open ID Connect / OAuth 2 provider and the example below demonstrates authenticating against IdentityServer3 running on localhost, using a custom sign in button, and supporting silent token renewal: |
| 32 | + |
| 33 | + <oauth2 authorization-url="https://localhost:44300/identity/connect/authorize" |
| 34 | + sign-out-url="https://localhost:44300/identity/connect/endsession" |
| 35 | + sign-out-append-token="true" |
| 36 | + sign-out-redirect-url="http://localhost:9000/#/landing" |
| 37 | + client-id="portal" |
| 38 | + redirect-url="http://localhost:9000" |
| 39 | + silent-token-redirect-url="http://localhost:9000/#/silent-renew" |
| 40 | + response-type="id_token token" |
| 41 | + scope="openid portaldashboard" |
| 42 | + template='views/templates/signInButton.html' |
| 43 | + auto-generate-nonce="true"> |
| 44 | + </oauth2> |
| 45 | + |
| 46 | +## Options |
| 47 | + |
| 48 | +The directive supports the following options specified as attributes on the oauth2 element: |
| 49 | + |
| 50 | +**Option** |**Description** |
| 51 | +-------------------------|----------------------------------------- |
| 52 | +auto-generate-nonce |*(Optional)* Should a nonce be autogenerated if none is supplied. Defaults to true. |
| 53 | +authorization-url |The identity servers authorization endpoint. |
| 54 | +button-class |*(Optional)* The class to assign to the sign in / out button. Defaults to btn btn-primary. |
| 55 | +client-id |The authorization server client ID. For social providers such as Google and Facebook this is typically generated in the developer portal. |
| 56 | +nonce |*(Optonal)* The nonce to supply to the identity server. If not specified and auto-generate-nonce is set to true then one will be autogenerated. |
| 57 | +redirectUrl |The redirect URL to supply to the identity server. If this doesn't match a URL registered in your identity server this will generally cause an error. |
| 58 | +responseType |The response type required from the identity server. Typically this is a combination of token and id_token. For example "id_token token". |
| 59 | +scope |The scopes requested from the authorization server. |
| 60 | +sign-in-text |*(Optional)* The text to apply to the sign in button. Defaults to "Sign in". |
| 61 | +sign-out-append-token |*(Optional)* Set this to true to append the ID token to the signout URL - a response_type of id_token must be used for this to wokr. Defaults to false. |
| 62 | +sign-out-text |*(Optional)* The text to apply to the sign out button. Defaults to "Sign out". |
| 63 | +sign-out-redirect-url |*(Optional)* The url to redirect the user to after sign out on the STS has completed. |
| 64 | +sign-out-url |*(Optional)* The identity servers sign out endpoint. If not specified then the local token will be deleted on sign out but the user will remain signed in to the identity server. |
| 65 | +silent-token-redirect-url|*(Optional)* If specified this will enable silent token renewal and the identity server will redirect to this URL. See section below for further details. |
| 66 | +state |*(Optional)* The value to use for CSRF protection. If not specified then a value will be autogenerated. |
| 67 | +template |*(Optional)* The Angular template to use for the sign in and out buttons. |
| 68 | + |
| 69 | +## Token Storage / State Management |
| 70 | + |
| 71 | +Data that is required over page refreshes is stored within [session storage](https://developer.mozilla.org/en/docs/Web/API/Window/sessionStorage): |
| 72 | + |
| 73 | +**Data** |**Description** |
| 74 | +------------------|--------------- |
| 75 | +oauthRedirectRoute|Used to store the application route to navigate to following a redirect from an identity server. It is set to null once that flow is complete. |
| 76 | +token |An object containing the tokens requested along with scopes and expiry date. |
| 77 | +verifyState |Used to verify the CSRF state across the identity server redirect chain. It is set to null once used. |
| 78 | + |
| 79 | +## Http Request Interception |
| 80 | + |
| 81 | +Once a valid token is obtained all http requests will be intercepted and have a Authorization header added in the format |
| 82 | + |
| 83 | + Bearer accesstoken |
| 84 | + |
| 85 | +If the token has expired then an oauth2:authExpired will be raised. |
| 86 | + |
| 87 | +## Silent Token Renewal |
| 88 | +*(Thanks to [Ciaran Jessup](https://github.com/ciaranj) for contributing this feature)* |
| 89 | + |
| 90 | +Silent token renewal uses a hidden iframe to contact the identity server and recieve a token 1 minute before it is expected to expire keeping a user logged in until they leave the web app. This does require them to have instructed the identity server to remember them when they logged in. |
| 91 | + |
| 92 | +To set this up within your Angular app set the silent-token-redirect-url attribute on the oauth2 element. This will register a route of silent-renew and so your attribute should redirect to that location. So for example if your app is running on localhost then the directive should be set as follows: |
| 93 | + |
| 94 | + <oauth2 ... silent-token-redirect-url="http://localhost/#/silent-renew" ...></oauth2> |
| 95 | + |
| 96 | +You will need to ensure your identity server supports a redirect back to this URL. If anything is misconfigured in the server you are likely to recieve an error similar to the below: |
| 97 | + |
| 98 | + Refused to display 'your-identityserver-url' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'. |
| 99 | + |
| 100 | +This is generally caused because your identity server is attempting to display content. |
| 101 | + |
| 102 | +For full details of the underlying implementation see these [commit notes](https://github.com/JamesRandall/AngularJS-OAuth2/commit/ff3e8e6825c18986c7545b75890287d3df8f8714). |
| 103 | + |
| 104 | +## Styling |
| 105 | + |
| 106 | +By default the directive comes configured for use within a Bootstrap 3 navigation bar. Basic styling can be undertaken using the button-class, sign-in-text and sign-out-text attributes but the appearance can be completely customized by providing a new template via the template attribute. The default template is defined as follows: |
| 107 | + |
| 108 | + <p class="navbar-btn"> |
| 109 | + <a class="{{buttonClass}}"> |
| 110 | + <span href="#" ng-hide="signedIn" ng-click="signIn()" >{{signInText}}</span> |
| 111 | + <span href="#" ng-show="signedIn" ng-click="signOut()">{{signOutText}}</span> |
| 112 | + </a> |
| 113 | + </p> |
| 114 | + |
| 115 | +## Events |
| 116 | + |
| 117 | +A variety of events are raised to indicate a change in state or communicate important information. |
| 118 | + |
| 119 | +**Event** |**Description** |
| 120 | +-------------------|--------------- |
| 121 | +oauth2:authError |An error occurred in the authentication process. The error is supplied as the event payload. |
| 122 | +oauth2:authExpired |The token has expired. The token is supplied as the event payload. |
| 123 | +oauth2:authSuccess |Indicates authorization has succeeded and a token returned. The token is supplied as the event payload. |
| 124 | + |
| 125 | +## Thanks |
| 126 | + |
| 127 | +Thanks to the many people who have helped to improve this code either through direct contributions or through discussion and raising issues. |
| 128 | + |
| 129 | +## License |
| 130 | + |
| 131 | +The MIT License (MIT) |
| 132 | + |
| 133 | +Copyright (c) 2016 James Randall |
| 134 | + |
| 135 | +Permission is hereby granted, free of charge, to any person obtaining a copy |
| 136 | +of this software and associated documentation files (the "Software"), to deal |
| 137 | +in the Software without restriction, including without limitation the rights |
| 138 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 139 | +copies of the Software, and to permit persons to whom the Software is |
| 140 | +furnished to do so, subject to the following conditions: |
| 141 | + |
| 142 | +The above copyright notice and this permission notice shall be included in all |
| 143 | +copies or substantial portions of the Software. |
| 144 | + |
| 145 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 146 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 147 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 148 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 149 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 150 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 151 | +SOFTWARE. |
4 | 152 |
|
5 | | -Full documentation will be available here shortly however in the meantime the plugin is documented in this [blog post](http://www.azurefromthetrenches.com/?p=2241). |
|
0 commit comments