Merge pull request #2216 from jean-merelis/master

Angular2 example
This commit is contained in:
Stian Thorgersen 2016-02-12 11:06:00 +01:00
commit b0dd65c706
10 changed files with 324 additions and 3 deletions

View file

@ -202,7 +202,28 @@ An Angular JS example using Keycloak to secure it.
If you are already logged in, you will not be asked for a username and password, but you will be redirected to If you are already logged in, you will not be asked for a username and password, but you will be redirected to
an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app. an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app.
Step 9: Pure HTML5/Javascript Example Step 10: Angular2 JS Example
----------------------------------
An Angular2 JS example using Keycloak to secure it. Angular2 is in beta version yet.
To install angular2
```
$ cd keycloak/examples/demo-template/angular2-product-app/src/main/webapp/
$ npm install
```
Transpile TypeScript to JavaScript before running the application.
```
$ npm run tsc
```
[http://localhost:8080/angular2-product](http://localhost:8080/angular2-product)
If you are already logged in, you will not be asked for a username and password, but you will be redirected to
an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app.
Step 11: Pure HTML5/Javascript Example
---------------------------------- ----------------------------------
An pure HTML5/Javascript example using Keycloak to secure it. An pure HTML5/Javascript example using Keycloak to secure it.
@ -211,7 +232,7 @@ An pure HTML5/Javascript example using Keycloak to secure it.
If you are already logged in, you will not be asked for a username and password, but you will be redirected to If you are already logged in, you will not be asked for a username and password, but you will be redirected to
an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app. an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app.
Step 10: Service Account Example Step 12: Service Account Example
================================ ================================
An example for retrieve service account dedicated to the Client Application itself (not to any user). An example for retrieve service account dedicated to the Client Application itself (not to any user).
@ -222,7 +243,7 @@ Client authentication is done with OAuth2 Client Credentials Grant in out-of-bou
The example also shows different methods of client authentication. There is ProductSAClientSecretServlet using traditional authentication with clientId and client_secret, The example also shows different methods of client authentication. There is ProductSAClientSecretServlet using traditional authentication with clientId and client_secret,
but there is also ProductSAClientSignedJWTServlet using client authentication with JWT signed by client private key. but there is also ProductSAClientSignedJWTServlet using client authentication with JWT signed by client private key.
Step 11: Offline Access Example Step 13: Offline Access Example
=============================== ===============================
An example for retrieve offline token, which is then saved to the database and can be used by application anytime later. Offline token An example for retrieve offline token, which is then saved to the database and can be used by application anytime later. Offline token
is valid even if user is already logged out from SSO. Server restart also won't invalidate offline token. Offline token can be revoked by the user in is valid even if user is already logged out from SSO. Server restart also won't invalidate offline token. Offline token can be revoked by the user in

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-examples-demo-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.9.0.Final-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak.example.demo</groupId>
<artifactId>angular2-product-example</artifactId>
<packaging>war</packaging>
<name>Angular2 Product Portal JS</name>
<description/>
<build>
<finalName>angular2-product</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,78 @@
import {Http, Headers,
RequestOptions, Response} from 'angular2/http';
import {Component} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {KeycloakService} from './keycloak';
@Component({
selector: 'my-app',
template:
`
<div id="content-area" class="col-md-9" role="main">
<div id="content">
<h1>Angular2 Product (Beta)</h1>
<h2><span>Products</span></h2>
<button type="button" (click)="logout()">Sign Out</button>
<button type="button" (click)="reloadData()">Reload</button>
<table class="table" [hidden]="!products.length">
<thead>
<tr>
<th>Product Listing</th>
</tr>
</thead>
<tbody>
<tr *ngFor="#p of products">
<td>{{p}}</td>
</tr>
</tbody>
</table>
</div>
</div>
`
})
export class AppComponent {
constructor(private _kc:KeycloakService, private http:Http){ }
products : string[] = [];
logout(){
this._kc.logout();
}
reloadData() {
//angular dont have http interceptor yet
this._kc.getToken().then(
token=>{
let headers = new Headers({
'Accept': 'application/json',
'Authorization': 'Bearer ' + token
});
let options = new RequestOptions({ headers: headers });
this.http.get('/database/products', options)
.map(res => <string[]> res.json())
.subscribe(
prods => this.products = prods,
error => console.log(error));
},
error=>{
console.log(error);
}
);
}
private handleError (error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}

View file

@ -0,0 +1,49 @@
import {Injectable} from 'angular2/core';
declare var Keycloak: any;
@Injectable()
export class KeycloakService {
static auth : any = {};
static init() : Promise<any>{
let keycloakAuth : any = new Keycloak('keycloak.json');
KeycloakService.auth.loggedIn = false;
return new Promise((resolve,reject)=>{
keycloakAuth.init({ onLoad: 'login-required' })
.success( () => {
KeycloakService.auth.loggedIn = true;
KeycloakService.auth.authz = keycloakAuth;
KeycloakService.auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/demo/tokens/logout?redirect_uri=/angular2-product/index.html";
resolve(null);
})
.error(()=> {
reject(null);
});
});
}
logout(){
console.log('*** LOGOUT');
KeycloakService.auth.loggedIn = false;
KeycloakService.auth.authz = null;
window.location.href = KeycloakService.auth.logoutUrl;
}
getToken(): Promise<string>{
return new Promise<string>((resolve,reject)=>{
if (KeycloakService.auth.authz.token) {
KeycloakService.auth.authz.updateToken(5).success(function() {
resolve(<string>KeycloakService.auth.authz.token);
})
.error(function() {
reject('Failed to refresh token');
});
}
});
}
}

View file

@ -0,0 +1,14 @@
import 'rxjs/Rx';
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_BINDINGS} from 'angular2/http';
import {KeycloakService} from './keycloak';
import {AppComponent} from './app';
KeycloakService.init().then(
o=>{
bootstrap(AppComponent,[HTTP_BINDINGS, KeycloakService]);
},
x=>{
window.location.reload();
}
);

View file

@ -0,0 +1,49 @@
<!doctype html>
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
<!-- 1. Load libraries -->
<!-- IE required polyfills, in this exact order -->
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/http.js"></script>
<script src="/auth/js/keycloak.js"></script>
<!-- 2. Configure SystemJS -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/main')
.then(null, console.error.bind(console));
</script>
</body>
</html>

View file

@ -0,0 +1,8 @@
{
"realm": "demo",
"realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
"auth-server-url": "/auth",
"ssl-required": "external",
"resource": "angular2-product",
"public-client": true
}

View file

@ -0,0 +1,25 @@
{
"name": "angular2-product-app",
"version": "1.0.0",
"scripts": {
"tsc": "tsc",
"tsc:w": "tsc -w",
"lite": "lite-server",
"start": "concurrent \"npm run tsc:w\" \"npm run lite\" "
},
"license": "ISC",
"dependencies": {
"angular2": "2.0.0-beta.3",
"systemjs": "0.19.6",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.0",
"zone.js": "0.5.11"
},
"devDependencies": {
"concurrently": "^1.0.0",
"lite-server": "^2.0.1",
"typescript": "^1.7.5"
}
}

View file

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es5",
"module": "system",
"moduleResolution": "node",
"sourceMap": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude": [
"node_modules"
]
}

View file

@ -147,6 +147,15 @@
"redirectUris": [ "redirectUris": [
"/angular-product/*" "/angular-product/*"
] ]
},
{
"clientId": "angular2-product",
"enabled": true,
"publicClient": true,
"baseUrl": "/angular2-product/index.html",
"redirectUris": [
"/angular2-product/*"
]
}, },
{ {
"clientId": "customer-portal-cli", "clientId": "customer-portal-cli",