2017-12-19 8 views
2

나는 완벽하게 작동하는 Angular 2+에 대해 adal.js 포트를 통해 Azure Active Directory 인증을 구현합니다.각도 4 : Observable not working

Google은 AdalService과의 통화를 처리하는 AuthenticationGuard을 보유하고 있습니다. AdalService에는 사용자가 로그인했는지 여부를 확인하는 기능인 ensureAuthenticatedAsync이 있으며, 그렇지 않은 경우 AD 로그인 페이지로 리디렉션됩니다.

AD 계정을 사용할 수없는 경우를 제외하고 사용자 지정 생성 토큰을 사용하여 로그인 할 수있는 새로운 요구 사항이 추가되었습니다. 일부 수정 후, 내 코드는 다음과 같습니다

authentication.guard.ts

public canActivate(route: ActivatedRouteSnapshot, state RouterStateSnapshot) : boolean { 
    ... 
    let params = route.queryParams; 
    let token = (params !== null && params['token'] !== undefined) ? params['token'] : null; 

    this.adalService.ensureAuthenticatedAsync(token); 
    ... 
    return true; 
} 

adal.service.ts

private context: adal.AuthenticationContext; 

public ensureAuthenticatedAsync(token: string | null = null) { 
    console.log('ensureAuthenticatedAsync', token); 
    this.isAuthenticated.subscribe(isAuthenticated => { 
     if (!isAuthenticated) { 
      console.log('not authenticated); 
      if (token === null) { 
       // forward to AAD login page -> this works perfectly 
       this.context.login(); 
      } else { 
       ... 
       console.log('accessToken before', this.accessToken); 
       this.customToken = token; 
       console.log('accessToken after', this.accessToken); 
       ... 
      } 
     } 
    }); 
} 

public get accessToken(): string { 
    console.log('customToken in get accessToken', this.customToken); 
    return (this.customToken === null) ? this.context.getCachedToken(this.adalClientId) : this.customToken; 
} 

public get isAuthenticated(): Observable<boolean> { 
    console.log('accessToken in get isAuthenticated', this.accessToken); 
    let isAuthenticated: boolean = (this.accessToken !== null); 
    return Observable.of(isAuthenticated); 
} 

app.component.ts

public ngOnInit(): void { 
    this.adalService.isAuthenticated.subscribe(isAuthenticated => { 
     if (isAuthenticated) { 
      // do some stuff here 
     } 
    }); 
} 
012 3,516,

app.routes.ts

export const ROUTES: Routes = [ 
    { path: 'Dashboard', component: DashboardComponent, canActivate: [AuthenticationGuard] }, 
    { path: 'Access-Denied', component: AccessDeniedComponent } 
]; 

이 콘솔에 로그인 무슨이다 :

authentication guard 
customToken in get accessToken null 
accessToken in get isAuthenticated null 
customToken in get accessToken null 
ensureAuthenticatedAsync 12345 
not authenticated 
customToken in get accessToken null 
accessToken before null 
customToken in get accessToken 12345 
accessToken after 12345 
customToken in get accessToken 12345 

정기적으로 페이지를 액세스은 (http://localhost:3000/Dashboard)가 제대로 후 AD 로그인 페이지로 리디렉션을 트리거 로그인 후 내 응용 프로그램으로 돌아갑니다. 거기에서 캐싱 된 AD 토큰이 변경되고 isAuthenticated가 가입 된 곳에서 트리거됩니다 (내 경우 app.component.ts).

그러나 토큰 (http://localhost:3000/Dashboard/?token=12345)을 사용하여 페이지에 액세스하는 것은 작동하지 않습니다. customToken이 param의 값으로 수정 되더라도 변경 내용이 전파되지 않고 isAuthenticated가 구독에 false으로 유지됩니다.

내가 뭔가를 놓쳤습니까?

+0

app.component.ts의 관련 코드를 추가하고 customToken이 수정되는 방법의 예를 추가 할 수 있습니까? btw 그것 isAuthenticated는 비동기 작업이 없으므로 관찰 할 수있는 을 반환합니다. –

+0

속성에 가입 한 app.component.ts에서 코드를 추가했습니다. customToken은 adal.service.ts에서 수정됩니다 (this.customToken = token). –

+0

관찰 할 수있는 : 나는 그 전에 간단한 부울 속성을했고 adal 로그인에서 돌아올 때 값을 새로 고치지 않았습니다. 나는 관찰 할 수있는 것을 시도해 보았다. –

답변

2

나는 문제가 가드 현지화에 대해 생각합니다.

가드가/Dashboard 경로에 있습니다. 따라서 http://localhost:3000/?token=12345 만로드하면 AuthenticationGuard가 호출되지 않으므로 AuthenticateAsync가 호출되지 않습니다. 따라서 리디렉션이없고 adal.service.ts에서 customToken을 업데이트하지 않았습니다.

당신이 appComponent에 보호 당신이 appComponent

편집에 "선도"경로에 가드를 사용해야 계산 된 결과를 사용하려면

: 문제는 당신이 반응 행동을 오해하고 있다는 것입니다. isAuthenticated가 구현되면 그것은 한 번 부울을 내 보낸 다음 완료합니다. 따라서 app.component의 구독은 한 번만 실행됩니다.

당신이 찾고있는 것은 필요에 따라 또는 customToken이 변경 될 때 새로운 데이터를 "밀어 넣을"수있는 주제입니다.

+0

이것은 오해입니다. 실제로 일치하지 않는 경로는/Dashboard로 리디렉션됩니다. 내 질문에 코드에 console.logs를 추가하여 내가 시도한 내용과 실제로 출력 한 내용을 보여줍니다. 실제로 업데이트되었지만 isAuthorized가 트리거되지 않고 app.component.ts의 구독에서 문제가 발생했는지 여부를 알 수 없습니다. –

+0

고마워요! 이것은 실제로 도움이되었습니다. 나는 BehaviorSubject로 바꾸었고 이것은 일을했다. –

+0

죄송합니다. 실제 답변이 댓글에 포함 된 이후로 나는 어떻게되었는지 알지 못했습니다. 나는 우리가 그것에 도달 한 방법이기 때문에, 당신의 대답을 올바른 것으로 표시했다. –

1

보십시오 : 당신의 adal.service.ts에서

:

import { Observable } from 'rxjs/Observable'; 
import { of } from 'rxjs/observable/of'; 
... 
public get isAuthenticated(): Observable<boolean> { 
let isAuthenticated: boolean = (this.accessToken !== null); 
return of(isAuthenticated); 
} 
+0

당신은 무슨 차이가 있는지 설명해 주시겠습니까? Observable.of (isAuthenticated)를 반환하는 대신'return of (isAuthenticated)'에서 다른 점은 무엇입니까? –

+1

rxjs 라이브러리를 별도로 사용하면 필요한 것만을 사용하여 prod 빌드를 최적화 할 수 있습니다. – anode7

+0

이 스크립트를 디버그하려면 자세한 정보가 필요합니다. – anode7