Skip to content

Commit 10204d2

Browse files
committed
fixed bugs
1 parent c540f42 commit 10204d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3395
-1659
lines changed

README.md

Lines changed: 83 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
# angular-oauth2-oidc
22

3-
Support for OAuth 2 and OpenId Connect (OIDC) in Angular.
3+
Support for OAuth 2 and OpenId Connect (OIDC) in Angular.
44

55
![OIDC Certified Logo](https://raw.githubusercontent.com/manfredsteyer/angular-oauth2-oidc/master/oidc.png)
66

77
## Credits
88

9-
- [generator-angular2-library](https://github.com/jvandemo/generator-angular2-library) for scaffolding an Angular library
109
- [jsrasign](https://kjur.github.io/jsrsasign/) for validating token signature and for hashing
1110
- [Identity Server](https://github.com/identityserver) for testing with an .NET/.NET Core Backend
1211
- [Keycloak (Redhat)](http://www.keycloak.org/) for testing with Java
@@ -17,6 +16,29 @@ Support for OAuth 2 and OpenId Connect (OIDC) in Angular.
1716
- Source Code Documentation: [https://manfredsteyer.github.io/angular-oauth2-oidc/docs](https://manfredsteyer.github.io/angular-oauth2-oidc/docs)
1817
- Community-provided sample implementation: [https://github.com/jeroenheijmans/sample-angular-oauth2-oidc-with-auth-guards/](https://github.com/jeroenheijmans/sample-angular-oauth2-oidc-with-auth-guards/)
1918

19+
## Breaking Change in Version 9
20+
21+
With regards to tree shaking, beginning with version 9, the ``JwksValidationHandler`` has been moved to a library of its own. If you need it for implementing **implicit flow**, please install it using npm:
22+
23+
```
24+
npm i angular-oauth2-oidc-jwks --save
25+
```
26+
27+
After that, you can import it into your application by using this:
28+
29+
```typescript
30+
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
31+
```
32+
33+
instead of that:
34+
35+
```typescript
36+
import { JwksValidationHandler } from 'angular-oauth2-oidc';
37+
```
38+
39+
Please note, that this dependency is not needed for the **code flow**, which is nowadays the **recommended** flow for single page applications. This also results in smaller bundle sizes.
40+
41+
2042
## Tested Environment
2143

2244
Successfully tested with **Angular 9** and its Router, PathLocationStrategy as well as HashLocationStrategy and CommonJS-Bundling via webpack. At server side we've used IdentityServer (.NET / .NET Core) and Redhat's Keycloak (Java).
@@ -36,12 +58,12 @@ Successfully tested with **Angular 9** and its Router, PathLocationStrategy as w
3658
- We plan one major release for each Angular version
3759
- Will contain new features
3860
- Will contain bug fixes and PRs
39-
- Critical Bugfixes on demand
61+
- Critical bugfixes on demand
4062

4163
## Contributions
4264

4365
- Feel free to file pull requests
44-
- The closed issues contain some ideas for PRs and enhancements (see labels)
66+
- The issues contain some ideas for PRs and enhancements (see labels)
4567
- If you want to contribute to the docs, you can do so in the `docs-src` folder. Make sure you update `summary.json` as well. Then generate the docs with the following commands:
4668

4769
``` sh
@@ -51,8 +73,9 @@ Successfully tested with **Angular 9** and its Router, PathLocationStrategy as w
5173

5274
## Features
5375

76+
- Logging in via Code Flow + PKCE
77+
- Hence, you are safe for the upcoming OAuth 2.1
5478
- Logging in via Implicit Flow (where a user is redirected to Identity Provider)
55-
- Logging in via Code Flow + PKCE
5679
- "Logging in" via Password Flow (where a user enters their password into the client)
5780
- Token Refresh for all supported flows
5881
- Automatically refreshing a token when/some time before it expires
@@ -64,20 +87,23 @@ Successfully tested with **Angular 9** and its Router, PathLocationStrategy as w
6487

6588
## Sample-Auth-Server
6689

67-
You can use the OIDC-Sample-Server mentioned in the samples for Testing. It assumes, that your Web-App runs on http://localhost:8080
90+
You can use the OIDC-Sample-Server used in our examples. It assumes, that your Web-App runs on http://localhost:4200
6891

69-
Username/Password: max/geheim
92+
Username/Password:
93+
- max/geheim
94+
- bob/bob
95+
- alice/alice
7096

7197
*clientIds:*
7298

73-
- spa-demo (implicit flow)
74-
- demo-resource-owner (resource owner password flow)
99+
- spa (Code Flow + PKCE)
100+
- implicit (implicit flow)
75101

76102
*redirectUris:*
77103

78-
- localhost:[8080-8089|4200-4202]
79-
- localhost:[8080-8089|4200-4202]/index.html
80-
- localhost:[8080-8089|4200-4202]/silent-refresh.html
104+
- localhost:[4200-4202]
105+
- localhost:[4200-4202]/index.html
106+
- localhost:[4200-4202]/silent-refresh.html
81107

82108
## Installing
83109

@@ -111,114 +137,67 @@ export class AppModule {
111137
}
112138
```
113139

114-
## Configuring for Implicit Flow
115-
116-
This section shows how to implement login leveraging implicit flow. This is the OAuth2/OIDC flow best suitable for
117-
Single Page Application. It sends the user to the Identity Provider's login page. After logging in, the SPA gets tokens.
118-
This also allows for single sign on as well as single sign off.
140+
# Logging in
119141

120-
To configure the library, the following sample uses the new configuration API introduced with Version 2.1.
121-
Hence, the original API is still supported.
142+
Since Version 8, this library supports code flow and [PKCE](https://tools.ietf.org/html/rfc7636) to align with the current draft of the [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13) document. This is also the foundation of the upcoming OAuth 2.1.
122143

123-
```TypeScript
124-
import { AuthConfig } from 'angular-oauth2-oidc';
125144

126-
export const authConfig: AuthConfig = {
127-
// Url of the Identity Provider
128-
issuer: 'https://steyer-identity-server.azurewebsites.net/identity',
145+
To configure your solution for code flow + PKCE you have to set the `responseType` to `code`:
129146

130-
// URL of the SPA to redirect the user to after login
131-
redirectUri: window.location.origin + '/index.html',
147+
```TypeScript
148+
import { AuthConfig } from 'angular-oauth2-oidc';
132149

133-
// The SPA's id. The SPA is registered with this id at the auth-server
134-
clientId: 'spa-demo',
150+
export const authCodeFlowConfig: AuthConfig = {
151+
// Url of the Identity Provider
152+
issuer: 'https://demo.identityserver.io',
135153

136-
// set the scope for the permissions the client should request
137-
// The first three are defined by OIDC. The 4th is a usecase-specific one
138-
scope: 'openid profile email voucher',
139-
}
140-
```
154+
// URL of the SPA to redirect the user to after login
155+
redirectUri: window.location.origin + '/index.html',
141156

142-
Configure the ``OAuthService`` with this config object when the application starts up:
157+
// The SPA's id. The SPA is registerd with this id at the auth-server
158+
// clientId: 'server.code',
159+
clientId: 'spa',
143160

144-
```TypeScript
145-
import { OAuthService } from 'angular-oauth2-oidc';
146-
import { JwksValidationHandler } from 'angular-oauth2-oidc';
147-
import { authConfig } from './auth.config';
148-
import { Component } from '@angular/core';
161+
// Just needed if your auth server demands a secret. In general, this
162+
// is a sign that the auth server is not configured with SPAs in mind
163+
// and it might not enforce further best practices vital for security
164+
// such applications.
165+
// dummyClientSecret: 'secret',
149166

150-
@Component({
151-
selector: 'flight-app',
152-
templateUrl: './app.component.html'
153-
})
154-
export class AppComponent {
167+
responseType: 'code',
155168

156-
constructor(private oauthService: OAuthService) {
157-
this.configure();
158-
}
169+
// set the scope for the permissions the client should request
170+
// The first four are defined by OIDC.
171+
// Important: Request offline_access to get a refresh token
172+
// The api scope is a usecase specific one
173+
scope: 'openid profile email offline_access api',
159174

160-
private configure() {
161-
this.oauthService.configure(authConfig);
162-
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
163-
this.oauthService.loadDiscoveryDocumentAndTryLogin();
164-
}
165-
}
166-
```
175+
showDebugInformation: true,
167176

168-
### Implementing a Login Form
169-
170-
After you've configured the library, you just have to call ``initImplicitFlow`` to login using OAuth2/ OIDC.
171-
172-
```TypeScript
173-
import { Component } from '@angular/core';
174-
import { OAuthService } from 'angular-oauth2-oidc';
177+
// Not recommented:
178+
// disablePKCI: true,
179+
};
180+
```
175181

176-
@Component({
177-
templateUrl: "app/home.html"
178-
})
179-
export class HomeComponent {
182+
After this, you can initialize the code flow using:
180183

181-
constructor(private oauthService: OAuthService) {
182-
}
184+
```TypeScript
185+
this.oauthService.initCodeFlow();
186+
```
183187

184-
public login() {
185-
this.oauthService.initLoginFlow();
186-
}
188+
There is also a convenience method `initLoginFlow` which initializes either the code flow or the implicit flow depending on your configuration.
187189

188-
public logoff() {
189-
this.oauthService.logOut();
190-
}
190+
```TypeScript
191+
this.oauthService.initLoginFlow();
192+
```
191193

192-
public get name() {
193-
let claims = this.oauthService.getIdentityClaims();
194-
if (!claims) return null;
195-
return claims.given_name;
196-
}
194+
Also -- as shown in the readme -- you have to execute the following code when bootstrapping to make the library to fetch the token:
197195

198-
}
196+
```TypeScript
197+
this.oauthService.configure(authCodeFlowConfig);
198+
this.oauthService.loadDiscoveryDocumentAndTryLogin();
199199
```
200200

201-
The following snippet contains the template for the login page:
202-
203-
```HTML
204-
<h1 *ngIf="!name">
205-
Hallo
206-
</h1>
207-
<h1 *ngIf="name">
208-
Hallo, {{name}}
209-
</h1>
210-
211-
<button class="btn btn-default" (click)="login()">
212-
Login
213-
</button>
214-
<button class="btn btn-default" (click)="logoff()">
215-
Logout
216-
</button>
217-
218-
<div>
219-
Username/Passwort zum Testen: max/geheim
220-
</div>
221-
```
222201

223202
### Skipping the Login Form
224203

@@ -227,44 +206,6 @@ If you don't want to display a login form that tells the user that they are redi
227206
This directly redirects the user to the identity server if there are no valid tokens. Ensure you have your `issuer` set to your discovery document endpoint!
228207

229208

230-
#### Manually skipping
231-
232-
This is sort of what ``this.oauthService.loadDiscoveryDocumentAndLogin();`` is doing under the hood. But this gives you a fair bit more control
233-
234-
```TypeScript
235-
this.oauthService
236-
.loadDiscoveryDocumentAndTryLogin(/* { your LoginOptions }*/) // checks to see if the current url contains id token and access token
237-
.(hasReceivedTokens => {
238-
// this would have stored all the tokens needed
239-
if (hasReceivedTokens) {
240-
// carry on with your app
241-
return Promise.resolve();
242-
243-
/* if you wish to do something when the user receives tokens from the identity server,
244-
* use the event stream or the `onTokenReceived` callback in LoginOptions.
245-
*
246-
* this.oauthService.events(filter(e => e.type === 'token_received')).subscribe()
247-
*/
248-
} else {
249-
// may want to check if you were previously authenticated
250-
if (this.oauthService.hasValidAccessToken() && this.oauthService.hasValidIdToken()) {
251-
return Promise.resolve();
252-
} else {
253-
// to safe guard this from progressing through the calling promise,
254-
// resolve it when it directed to the sign up page
255-
return new Promise(resolve => {
256-
this.oauthService.initLoginFlow();
257-
// example if you are using explicit flow
258-
this.window.addEventListener('unload', () => {
259-
resolve(true);
260-
});
261-
});
262-
}
263-
}
264-
})
265-
```
266-
267-
268209
### Calling a Web API with an Access Token
269210

270211
You can automate this task by switching ``sendAccessToken`` on and by setting ``allowedUrls`` to an array with prefixes for the respective URLs. Use lower case for the prefixes.
@@ -280,10 +221,6 @@ OAuthModule.forRoot({
280221

281222
If you need more versatility, you can look in the [documentation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/working-with-httpinterceptors.html) how to setup a custom interceptor.
282223

283-
## Code Flow + PKCE
284-
285-
See docs: https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/code-flow-+-pcke.html
286-
287224
## Token Refresh
288225

289226
See docs: https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/refreshing-a-token.html
@@ -292,6 +229,10 @@ See docs: https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-do
292229

293230
If you use the ``PathLocationStrategy`` (which is on by default) and have a general catch-all-route (``path: '**'``) you should be fine. Otherwise look up the section ``Routing with the HashStrategy`` in the [documentation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/).
294231

232+
## Implicit Flow
233+
234+
Nowadays, using code flow + PKCE -- as shown above -- is the recommended OAuth 2/OIDC flow for SPAs. To use the older implicit flow, lookup this docs: https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/implicit-flow.html
235+
295236
## More Documentation (!)
296237

297238
See the [documentation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/) for more information about this library.

docs-src/code-flow.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ Also -- as shown in the readme -- you have to execute the following code when bo
5656

5757
```TypeScript
5858
this.oauthService.configure(authCodeFlowConfig);
59-
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
6059
this.oauthService.loadDiscoveryDocumentAndTryLogin();
6160
```
6261

docs-src/implicit-flow-config-discovery.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Original Config API
22

3+
> This describes the older config API which is nowadays only supported for the sake of backwards compatibility.
4+
35
To configure the library you just have to set some properties on startup. For this, the following sample uses the constructor of the AppComponent which is called before routing kicks in.
46

57
Please note that the following sample uses the original config API. For information about the new config API have a look to the project's README above.

0 commit comments

Comments
 (0)