IdentityServer4 oidc w / angular2 Guard始终为False

时间:2017-02-14 19:32:23

标签: javascript angular

我有成功验证用户的身份,它将用户传递回运行的主站点

<script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client/1.2.2/oidc-client.min.js"></script>
<h1 id="waiting">Waiting...</h1>
<div id="error"></div>
<script>
    new Oidc.UserManager().signinRedirectCallback().then(function (user) {
        if (user == null) {
            document.getElementById("waiting").style.display = "none";
            document.getElementById("error").innerText = "No sign-in request pending.";
        }
        else {
            window.location = "/";
        }
    })
    .catch(function (er) {
        document.getElementById("waiting").style.display = "none";
        document.getElementById("error").innerText = er.message;
    });
</script>

但是当它成为主页&#34; /&#34;由于

,它会继续回到未经验证的状态
 import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { UniversalModule } from 'angular2-universal';

import { AppComponent } from './components/app/app.component';
import { HomeComponent } from './components/home/home.component';
import { UnauthorizedComponent } from './components/unauthorized/unauthorized.component';

import { AuthService } from './services/shared/auth.service';
import { AuthGuardService } from './services/shared/auth-guard.service';

@NgModule({
    bootstrap: [ AppComponent ],
    declarations: [
        AppComponent,
        HomeComponent, 
        UnauthorizedComponent
    ],
    imports: [
        UniversalModule, // Must be first import. This automatically imports          BrowserModule, HttpModule, and JsonpModule too.
        RouterModule.forRoot([
            {
                path: '', redirectTo: 'home', pathMatch: 'full'
            },
            {
                path: 'home',
                component: HomeComponent,
                canActivate: [AuthGuardService]
            },
            {
                path: 'unauthorized',
                component: UnauthorizedComponent
            }
        ])
    ],
    providers: [AuthService, AuthGuardService]
})
export class AppModule {
}

AuthGuard的位置

    import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

import { AuthService } from './auth.service';

@Injectable()
export class AuthGuardService implements CanActivate {

    constructor(private authService: AuthService, private router: Router) {
    }
    canActivate() {
        if (this.authService.loggedIn)
        {
            alert("this"); //<--- never happens 
            return true;
        }
      alert(this.authService.loggedIn); //<---  always false, happens before everything else?
        this.router.navigate(['unauthorized']);

    }
}

AuthService的位置

    import { Injectable, EventEmitter } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';

import { UserManager, Log, MetadataService, User } from 'oidc-client';

@Injectable()
export class AuthService {
    mgr: UserManager = new UserManager(settings);
    userLoadededEvent: EventEmitter<User> = new EventEmitter<User>();
    currentUser: User;
    loggedIn: boolean = false;

    authHeaders: Headers;


    constructor(private http: Http) {
        this.mgr.getUser()
            .then((user) => {
                if (user) {
                    this.loggedIn = true;
                    alert("loggedin"); //<--- Happens all the time
                    this.currentUser = user;
                    this.userLoadededEvent.emit(user);
                }
                else {
                    this.loggedIn = false;
                }
            })
            .catch((err) => {
                this.loggedIn = false;
            });
        this.mgr.events.addUserUnloaded((e) => {
            this.loggedIn = false;
        });
    }
    clearState() {
        this.mgr.clearStaleState().then(function () {
            console.log("clearStateState success");
        }).catch(function (e) {
            console.log("clearStateState error", e.message);
        });
    }

    getUser() {
        this.mgr.getUser().then((user) => {
            console.log("got user", user);
            this.userLoadededEvent.emit(user);
        }).catch(function (err) {
            console.log(err);
        });
    }

    removeUser() {
        this.mgr.removeUser().then(() => {
            this.userLoadededEvent.emit(null);
            console.log("user removed");
        }).catch(function (err) {
            console.log(err);
        });
    }

    startSigninMainWindow() {
        this.mgr.signinRedirect({ data: 'some data' }).then(function () {
            console.log("signinRedirect done");
        }).catch(function (err) {
            console.log(err);
        });
    }
    endSigninMainWindow() {
        this.mgr.signinRedirectCallback().then(function (user) {
            console.log("signed in", user);
        }).catch(function (err) {
            console.log(err);
        });
    }

    startSignoutMainWindow() {
        this.mgr.signoutRedirect().then(function (resp) {
            console.log("signed out", resp);
            setTimeout(5000, () => {
                console.log("testing to see if fired...");

            })
        }).catch(function (err) {
            console.log(err);
        });
    };

    endSignoutMainWindow() {
        this.mgr.signoutRedirectCallback().then(function (resp) {
            console.log("signed out", resp);
        }).catch(function (err) {
            console.log(err);
        });
    };
    /**
     * Example of how you can make auth request using angulars http methods.
     * @param options if options are not supplied the default content type is application/json
     */
    AuthGet(url: string, options?: RequestOptions): Observable<Response> {

        if (options) {
            options = this._setRequestOptions(options);
        }
        else {
            options = this._setRequestOptions();
        }
        return this.http.get(url, options);
    }
    /**
     * @param options if options are not supplied the default content type is application/json
     */
    AuthPut(url: string, data: any, options?: RequestOptions): Observable<Response> {

        let body = JSON.stringify(data);

        if (options) {
            options = this._setRequestOptions(options);
        }
        else {
            options = this._setRequestOptions();
        }
        return this.http.put(url, body, options);
    }
    /**
     * @param options if options are not supplied the default content type is application/json
     */
    AuthDelete(url: string, options?: RequestOptions): Observable<Response> {

        if (options) {
            options = this._setRequestOptions(options);
        }
        else {
            options = this._setRequestOptions();
        }
        return this.http.delete(url, options);
    }
    /**
     * @param options if options are not supplied the default content type is application/json
     */
    AuthPost(url: string, data: any, options?: RequestOptions): Observable<Response> {

        let body = JSON.stringify(data);

        if (options) {
            options = this._setRequestOptions(options);
        }
        else {
            options = this._setRequestOptions();
        }
        return this.http.post(url, body, options);
    }


    private _setAuthHeaders(user: any) {
        this.authHeaders = new Headers();
        this.authHeaders.append('Authorization', user.token_type + " " + user.access_token);
        this.authHeaders.append('Content-Type', 'application/json');
    }
    private _setRequestOptions(options?: RequestOptions) {

        if (options) {
            options.headers.append(this.authHeaders.keys[0], this.authHeaders.values[0]);
        }
        else {
            options = new RequestOptions({ headers: this.authHeaders, body: "" });
        }

        return options;
    }

}

const settings: any = {
    authority: 'http://localhost:5000/',
    client_id: 'js',
    redirect_uri: 'http://localhost:38881/auth',
    post_logout_redirect_uri: 'http://localhost:38881/',
    response_type: 'id_token token',
    scope: 'openid profile api',

    silent_redirect_uri: 'http://localhost:38881',
    automaticSilentRenew: true,
    //silentRequestTimeout:10000,

    filterProtocolClaims: true,
    loadUserInfo: true
};

问题在于,即使发出警报,任何试图回家或/或导致未经授权的行为(&#34;已登录&#34;);发生

好像是 警报(this.authService.loggedIn); //&lt; ---总是假的,发生在其他所有事情之前,这就是为什么即使authservice的结果没有返回也能解决问题的原因

1 个答案:

答案 0 :(得分:2)

我有同样的问题。问题是AuthService构造函数中的Promise在AuthGuardService检查用户是否已登录后解析。为了解决这个问题,我在AuthService中创建了一个新函数:

isLoggedIn(): Observable<boolean> {
  return Observable.fromPromise(this.mgr.getUser()).map<User, boolean>((user) => {
    if (user) return true;
    else return false;
  });
}

然后,重写AuthGuardService的canActivate函数以使用isLoggedIn()函数而不是依赖于AuthService构造函数:

canActivate() {
    let self = this;
    let isloggedIn = this.authService.isLoggedIn();
    isloggedIn.subscribe((loggedin) => {
        if(!loggedin){
            self.router.navigate(['unauthorized']);
        }
    });
    return isloggedIn;
}

这个canActivate实现返回一个Observable而不是boolean,让它等待AuthService中的Promise完成。还有一个订阅,所以我们可以决定是否重定向到未授权。

另请参阅此问题:https://github.com/jmurphzyo/Angular2OidcClient/issues/21