Merge
This commit is contained in:
commit
e3fdd2f39e
@ -19,8 +19,6 @@ services:
|
||||
- BasketUrl=http://basket.api:5103
|
||||
ports:
|
||||
- "5100:5100"
|
||||
links:
|
||||
- identity.service:10.0.75.1
|
||||
|
||||
webspa:
|
||||
environment:
|
||||
|
@ -47,3 +47,5 @@ services:
|
||||
|
||||
basket.data:
|
||||
image: redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
@ -41,8 +41,8 @@ namespace eShopOnContainers.Identity.Configuration
|
||||
ClientName = "eShop SPA OpenId Client",
|
||||
AllowedGrantTypes = GrantTypes.Implicit,
|
||||
AllowAccessTokensViaBrowser = true,
|
||||
RedirectUris = { $"{clientsUrl["Spa"]}/callback.html" },
|
||||
PostLogoutRedirectUris = { $"{clientsUrl["Spa"]}/index.html" },
|
||||
RedirectUris = { $"{clientsUrl["Spa"]}/" },
|
||||
PostLogoutRedirectUris = { $"{clientsUrl["Spa"]}/" },
|
||||
AllowedCorsOrigins = { $"{clientsUrl["Spa"]}" },
|
||||
AllowedScopes =
|
||||
{
|
||||
@ -83,7 +83,8 @@ namespace eShopOnContainers.Identity.Configuration
|
||||
{
|
||||
$"{clientsUrl["Mvc"]}/signin-oidc",
|
||||
"http://104.40.62.65:5100/signin-oidc",
|
||||
"http://localhost:5100"
|
||||
"http://localhost:5100/signin-oidc",
|
||||
"http://13.88.8.119:5100/signin-oidc"
|
||||
},
|
||||
PostLogoutRedirectUris = new List<string>
|
||||
{
|
||||
|
@ -8,7 +8,8 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<esh-basket-status></esh-basket-status>
|
||||
<esh-basket-status *ngIf="Authenticated"></esh-basket-status>
|
||||
<esh-identity *ngIf="!Authenticated"></esh-identity>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -39,3 +40,5 @@
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
|
||||
import { DataService } from './shared/services/data.service';
|
||||
import { SecurityService } from './shared/services/security.service';
|
||||
|
||||
/*
|
||||
* App Component
|
||||
@ -10,22 +12,24 @@ import { DataService } from './shared/services/data.service';
|
||||
*/
|
||||
|
||||
@Component({
|
||||
selector: 'appc-app',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
templateUrl: './app.component.html'
|
||||
selector: 'appc-app',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
templateUrl: './app.component.html'
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
private Authenticated: boolean = false;
|
||||
subscription: Subscription;
|
||||
|
||||
constructor(private titleService: Title, private securityService: SecurityService) {
|
||||
|
||||
constructor(private titleService: Title) {
|
||||
}
|
||||
|
||||
}
|
||||
ngOnInit() {
|
||||
console.log('app on init');
|
||||
this.subscription = this.securityService.authenticationChallenge$.subscribe(res => this.Authenticated = res);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
}
|
||||
|
||||
public setTitle(newTitle: string) {
|
||||
this.titleService.setTitle('eShopOnContainers');
|
||||
}
|
||||
public setTitle(newTitle: string) {
|
||||
this.titleService.setTitle('eShopOnContainers');
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,15 @@ export class BasketStatusComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.subscription = this.basketEvents.addItemToBasket$.subscribe(
|
||||
item => {
|
||||
console.log('element received in basket');
|
||||
console.log(item);
|
||||
this.service.setBasket(item);
|
||||
this.service.getBasket().subscribe(basket => {
|
||||
this.badge = basket.items.length;
|
||||
this.service.setBasket(item).subscribe(res => {
|
||||
console.log(res);
|
||||
this.service.getBasket().subscribe(basket => {
|
||||
this.badge = basket.items.length;
|
||||
console.log('response from basket api');
|
||||
console.log(basket.items.length);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Response } from '@angular/http';
|
||||
import { Response, Headers } from '@angular/http';
|
||||
|
||||
import { DataService } from '../shared/services/data.service';
|
||||
import { SecurityService } from '../shared/services/security.service';
|
||||
import { IBasket } from '../shared/models/basket.model';
|
||||
import { IBasketItem } from '../shared/models/basketItem.model';
|
||||
|
||||
@ -19,13 +20,16 @@ export class BasketService {
|
||||
items: []
|
||||
};
|
||||
|
||||
constructor(private service: DataService) {
|
||||
constructor(private service: DataService, private authService: SecurityService) {
|
||||
this.basket.items = [];
|
||||
}
|
||||
|
||||
setBasket(item) {
|
||||
setBasket(item): Observable<boolean> {
|
||||
console.log('set basket');
|
||||
this.basket.items.push(item);
|
||||
this.service.post(this.basket.buyerId, this.basket.items);
|
||||
return this.service.post(this.basketUrl + '/', this.basket).map((response: Response) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
getBasket(): Observable<IBasket> {
|
||||
|
@ -0,0 +1 @@
|
||||
<button (click)="login()">Login</button>
|
@ -0,0 +1,3 @@
|
||||
.identity {
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
import { Component, OnInit, OnChanges, Output, Input, EventEmitter } from '@angular/core';
|
||||
|
||||
import { IIdentity } from '../../models/identity.model';
|
||||
import { SecurityService } from '../../services/security.service';
|
||||
|
||||
@Component({
|
||||
selector: 'esh-identity',
|
||||
templateUrl: './identity.html',
|
||||
styleUrls: ['./identity.scss']
|
||||
})
|
||||
export class Identity implements OnInit {
|
||||
constructor(private service: SecurityService) {
|
||||
}
|
||||
|
||||
@Output()
|
||||
changed: EventEmitter<number> = new EventEmitter<number>();
|
||||
|
||||
@Input()
|
||||
model: IIdentity;
|
||||
|
||||
ngOnInit() {
|
||||
console.log("ngOnInit _securityService.AuthorizedCallback");
|
||||
|
||||
if (window.location.hash) {
|
||||
this.service.AuthorizedCallback();
|
||||
console.log('isAutorized?');
|
||||
console.log(this.service.IsAuthorized);
|
||||
}
|
||||
}
|
||||
|
||||
login() {
|
||||
this.service.Authorize();
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.service.Logoff();
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export interface IIdentity {
|
||||
|
||||
}
|
@ -8,15 +8,19 @@ import { Observer } from 'rxjs/Observer';
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/catch';
|
||||
|
||||
import { SecurityService } from './security.service';
|
||||
|
||||
@Injectable()
|
||||
export class DataService {
|
||||
|
||||
constructor(private http: Http) { }
|
||||
constructor(private http: Http, private securityService: SecurityService) { }
|
||||
|
||||
get(url: string, params?: any): Observable<Response> {
|
||||
let options: RequestOptionsArgs = {};
|
||||
options.headers = new Headers();
|
||||
this.addCors(options);
|
||||
|
||||
if (this.securityService) {
|
||||
options.headers = new Headers();
|
||||
options.headers.append("Authorization", "Bearer " + this.securityService.GetToken());
|
||||
}
|
||||
|
||||
return this.http.get(url, options).map(
|
||||
(res: Response) => {
|
||||
@ -24,13 +28,18 @@ export class DataService {
|
||||
}).catch(this.handleError);
|
||||
}
|
||||
|
||||
post(url: string, data: any, params?: any) {
|
||||
return this.http.post(url, data, params);
|
||||
}
|
||||
post(url: string, data: any, params?: any): Observable<Response> {
|
||||
let options: RequestOptionsArgs = {};
|
||||
|
||||
private addCors(options: RequestOptionsArgs): RequestOptionsArgs {
|
||||
options.headers.append('Access-Control-Allow-Origin', '*');
|
||||
return options;
|
||||
if (this.securityService) {
|
||||
options.headers = new Headers();
|
||||
options.headers.append("Authorization", "Bearer " + this.securityService.GetToken());
|
||||
}
|
||||
|
||||
return this.http.post(url, data, options).map(
|
||||
(res: Response) => {
|
||||
return res;
|
||||
}).catch(this.handleError);
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
|
@ -0,0 +1,247 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http, Response, Headers } from '@angular/http';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
//import { Configuration } from '../app.constants';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class SecurityService {
|
||||
|
||||
private actionUrl: string;
|
||||
private headers: Headers;
|
||||
private storage: any;
|
||||
private authenticationSource = new Subject<boolean>();
|
||||
authenticationChallenge$ = this.authenticationSource.asObservable();
|
||||
|
||||
constructor(private _http: Http, private _router: Router) {
|
||||
|
||||
//this.actionUrl = _configuration.Server + 'api/DataEventRecords/';
|
||||
|
||||
this.headers = new Headers();
|
||||
this.headers.append('Content-Type', 'application/json');
|
||||
this.headers.append('Accept', 'application/json');
|
||||
this.storage = sessionStorage; //localStorage;
|
||||
|
||||
if (this.retrieve("IsAuthorized") !== "") {
|
||||
//this.HasAdminRole = this.retrieve("HasAdminRole");
|
||||
this.IsAuthorized = this.retrieve("IsAuthorized");
|
||||
}
|
||||
}
|
||||
|
||||
public IsAuthorized: boolean;
|
||||
//public HasAdminRole: boolean;
|
||||
|
||||
public GetToken(): any {
|
||||
return this.retrieve("authorizationData");
|
||||
}
|
||||
|
||||
public ResetAuthorizationData() {
|
||||
this.store("authorizationData", "");
|
||||
this.store("authorizationDataIdToken", "");
|
||||
|
||||
this.IsAuthorized = false;
|
||||
//this.HasAdminRole = false;
|
||||
this.store("HasAdminRole", false);
|
||||
this.store("IsAuthorized", false);
|
||||
}
|
||||
|
||||
public UserData: any;
|
||||
public SetAuthorizationData(token: any, id_token:any) {
|
||||
if (this.retrieve("authorizationData") !== "") {
|
||||
this.store("authorizationData", "");
|
||||
}
|
||||
|
||||
this.store("authorizationData", token);
|
||||
this.store("authorizationDataIdToken", id_token);
|
||||
this.IsAuthorized = true;
|
||||
this.store("IsAuthorized", true);
|
||||
//emit observable
|
||||
this.authenticationSource.next(true);
|
||||
|
||||
this.getUserData()
|
||||
.subscribe(data => this.UserData = data,
|
||||
error => this.HandleError(error),
|
||||
() => {
|
||||
console.log(this.UserData);
|
||||
});
|
||||
}
|
||||
|
||||
public Authorize() {
|
||||
this.ResetAuthorizationData();
|
||||
|
||||
console.log("BEGIN Authorize, no auth data");
|
||||
|
||||
var authorizationUrl = 'http://localhost:5105/connect/authorize';
|
||||
var client_id = 'js';
|
||||
var redirect_uri = 'http://localhost:5104/';
|
||||
var response_type = "id_token token";
|
||||
var scope = "openid profile orders basket";
|
||||
var nonce = "N" + Math.random() + "" + Date.now();
|
||||
var state = Date.now() + "" + Math.random();
|
||||
|
||||
this.store("authStateControl", state);
|
||||
this.store("authNonce", nonce);
|
||||
console.log("AuthorizedController created. adding myautostate: " + this.retrieve("authStateControl"));
|
||||
|
||||
var url =
|
||||
authorizationUrl + "?" +
|
||||
"response_type=" + encodeURI(response_type) + "&" +
|
||||
"client_id=" + encodeURI(client_id) + "&" +
|
||||
"redirect_uri=" + encodeURI(redirect_uri) + "&" +
|
||||
"scope=" + encodeURI(scope) + "&" +
|
||||
"nonce=" + encodeURI(nonce) + "&" +
|
||||
"state=" + encodeURI(state);
|
||||
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
public AuthorizedCallback() {
|
||||
console.log("BEGIN AuthorizedCallback, no auth data");
|
||||
this.ResetAuthorizationData();
|
||||
|
||||
var hash = window.location.hash.substr(1);
|
||||
|
||||
var result: any = hash.split('&').reduce(function (result : any, item: string) {
|
||||
var parts = item.split('=');
|
||||
result[parts[0]] = parts[1];
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
console.log(result);
|
||||
console.log("AuthorizedCallback created, begin token validation");
|
||||
|
||||
var token = "";
|
||||
var id_token = "";
|
||||
var authResponseIsValid = false;
|
||||
if (!result.error) {
|
||||
|
||||
if (result.state !== this.retrieve("authStateControl")) {
|
||||
console.log("AuthorizedCallback incorrect state");
|
||||
} else {
|
||||
|
||||
token = result.access_token;
|
||||
id_token = result.id_token
|
||||
|
||||
var dataIdToken: any = this.getDataFromToken(id_token);
|
||||
console.log(dataIdToken);
|
||||
|
||||
// validate nonce
|
||||
if (dataIdToken.nonce !== this.retrieve("authNonce")) {
|
||||
console.log("AuthorizedCallback incorrect nonce");
|
||||
} else {
|
||||
this.store("authNonce", "");
|
||||
this.store("authStateControl", "");
|
||||
|
||||
authResponseIsValid = true;
|
||||
console.log("AuthorizedCallback state and nonce validated, returning access token");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (authResponseIsValid) {
|
||||
this.SetAuthorizationData(token, id_token);
|
||||
console.log(this.retrieve("authorizationData"));
|
||||
|
||||
// router navigate to DataEventRecordsList
|
||||
this._router.navigate(['/dataeventrecords/list']);
|
||||
}
|
||||
else {
|
||||
this.ResetAuthorizationData();
|
||||
this._router.navigate(['/Unauthorized']);
|
||||
}
|
||||
}
|
||||
|
||||
public Logoff() {
|
||||
// /connect/endsession?id_token_hint=...&post_logout_redirect_uri=https://myapp.com
|
||||
console.log("BEGIN Authorize, no auth data");
|
||||
|
||||
var authorizationUrl = 'http://localhost:5105/connect/endsession';
|
||||
console.log(this.retrieve("authorizationDataIdToken"));
|
||||
var id_token_hint = this.retrieve("authorizationDataIdToken");
|
||||
var post_logout_redirect_uri = 'http://localhost:5104/';
|
||||
|
||||
var url =
|
||||
authorizationUrl + "?" +
|
||||
"id_token_hint=" + encodeURI(id_token_hint) + "&" +
|
||||
"post_logout_redirect_uri=" + encodeURI(post_logout_redirect_uri);
|
||||
|
||||
this.ResetAuthorizationData();
|
||||
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
public HandleError(error: any) {
|
||||
console.log(error);
|
||||
if (error.status == 403) {
|
||||
this._router.navigate(['/Forbidden'])
|
||||
}
|
||||
else if (error.status == 401) {
|
||||
this.ResetAuthorizationData();
|
||||
this._router.navigate(['/Unauthorized'])
|
||||
}
|
||||
}
|
||||
|
||||
private urlBase64Decode(str: string) {
|
||||
var output = str.replace('-', '+').replace('_', '/');
|
||||
switch (output.length % 4) {
|
||||
case 0:
|
||||
break;
|
||||
case 2:
|
||||
output += '==';
|
||||
break;
|
||||
case 3:
|
||||
output += '=';
|
||||
break;
|
||||
default:
|
||||
throw 'Illegal base64url string!';
|
||||
}
|
||||
|
||||
return window.atob(output);
|
||||
}
|
||||
|
||||
private getDataFromToken(token: any) {
|
||||
var data = {};
|
||||
if (typeof token !== 'undefined') {
|
||||
var encoded = token.split('.')[1];
|
||||
data = JSON.parse(this.urlBase64Decode(encoded));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private retrieve(key: string): any {
|
||||
var item = this.storage.getItem(key);
|
||||
|
||||
if (item && item !== 'undefined') {
|
||||
return JSON.parse(this.storage.getItem(key));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private store(key: string, value: any) {
|
||||
this.storage.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
|
||||
private getUserData = (): Observable<string[]> => {
|
||||
this.setHeaders();
|
||||
return this._http.get('http://localhost:5105/connect/userinfo', {
|
||||
headers: this.headers,
|
||||
body: ''
|
||||
}).map(res => res.json());
|
||||
}
|
||||
|
||||
private setHeaders() {
|
||||
this.headers = new Headers();
|
||||
this.headers.append('Content-Type', 'application/json');
|
||||
this.headers.append('Accept', 'application/json');
|
||||
|
||||
var token = this.GetToken();
|
||||
|
||||
if (token !== "") {
|
||||
this.headers.append('Authorization', 'Bearer ' + token);
|
||||
}
|
||||
}
|
||||
}
|
@ -17,9 +17,11 @@ import { DataService } from './services/data.service';
|
||||
import { UtilityService } from './services/utility.service';
|
||||
import { UppercasePipe } from './pipes/uppercase.pipe';
|
||||
import { BasketWrapperService} from './services/basket.wrapper.service';
|
||||
import { SecurityService } from './services/security.service';
|
||||
|
||||
//Components:
|
||||
import {Pager } from './components/pager/pager';
|
||||
import {Identity } from './components/identity/identity';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -39,7 +41,8 @@ import {Pager } from './components/pager/pager';
|
||||
ErrorSummaryComponent,
|
||||
PageHeadingComponent,
|
||||
UppercasePipe,
|
||||
Pager
|
||||
Pager,
|
||||
Identity
|
||||
],
|
||||
exports: [
|
||||
// Modules
|
||||
@ -57,9 +60,9 @@ import {Pager } from './components/pager/pager';
|
||||
//HeaderComponent,
|
||||
PageHeadingComponent,
|
||||
UppercasePipe,
|
||||
Pager
|
||||
Pager,
|
||||
Identity
|
||||
]
|
||||
|
||||
})
|
||||
export class SharedModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
@ -70,7 +73,8 @@ export class SharedModule {
|
||||
DataService,
|
||||
FormControlService,
|
||||
UtilityService,
|
||||
BasketWrapperService
|
||||
BasketWrapperService,
|
||||
SecurityService
|
||||
]
|
||||
};
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ namespace eShopConContainers.WebSPA
|
||||
.UseKestrel()
|
||||
.UseConfiguration(config)
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseUrls("http://localhost:5104/")
|
||||
.UseIISIntegration()
|
||||
//.UseUrls("http://localhost:5104/")
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user