Неявный поток OpenIdDict для клиентов Angular и Ionic

Мы использовали OpenIdDict с потоком паролей.

Но: мы хотим переключиться на неявный поток (всплывающее окно с сервера авторизации openiddict). Я могу найти образец для приложения ASP.NET, но мы хотим использовать его в: 1/на веб-сайте angular 1.0 2/в приложении Ionic 2.0

Может кто-нибудь дать несколько советов, как это сделать? (пример Aurelia близок, но мы не можем заставить его работать в Ionic или Angular). Какие библиотеки мы можем использовать, какие вызовы мы должны делать?

Большое спасибо,

Frank

person Frank P    schedule 12.01.2017    source источник


Ответы (1)


Я использовал неявный поток с OpenIddict только из приложений angular2 с машинописным текстом, но я настоятельно рекомендую вам использовать oidc-client . В любом случае применяется одна и та же методология для всех SPA.

Вы можете создать угловую службу, которая обертывает эту библиотеку, содержащую UserManager и несколько сокращений методов, таких как signIn, signInCallback...

@Injectable()
export class OAuthService {
    private client: UserManager;
    private user: Promise<User | null>;

    constructor(private ngZone: NgZone, @Inject(OAUTH_CONFIG_TOKEN) options: IOAuthConfig) {
        Log.logger = console;

        Log.level = Log.INFO;
        this.client = new UserManager(<UserManagerSettings>{
            authority: options.authority, // the url of your openiddict service
            client_id: options.client_id, // your openiddict application id
            redirect_uri: options.redirect_uri, // the url of your app after login
            post_logout_redirect_uri: options.post_logout_redirect_uri, // the url of your app after logout
            scope: options.scope, // your openid scopes like 'openid email profile roles'
            response_type: 'id_token token', //id + access token
            filterProtocolClaims: true,
            loadUserInfo: true,
        });
        this.client.events.addUserLoaded(user => {
            this.user = Promise.resolve(user);
            Log.logger.info('OAuthService: User loaded');
        });
        this.client.events.addUserSignedOut(() => Log.logger.info('OAuthService: User signed out'));
        this.client.events.addUserUnloaded(() => Log.logger.info('OAuthService: User unloaded'));
        this.client.events.addSilentRenewError(err => Log.logger.error(err));
        this.user = this.ngZone.runOutsideAngular(() => {
            return this.client.getUser().then((user) => {
                if (user == null) {
                    return null;
                }
                return user;
            });
        });
    }

    public get events(): UserManagerEvents {
        return this.client.events;
    }


    public signin(): Promise<any> {
        return this.ngZone.runOutsideAngular(() => {
            return this.client.signinRedirect()
                .catch(err => Log.logger.error(err));
        });
    }

    public signinCallback(): Promise<User|null> {
        this.user = this.ngZone.runOutsideAngular(() => {
            return this.client.signinRedirectCallback()
                .then(user => {
                    if (user == null) {
                        return null;
                    }
                    return user;
                })
                .catch(err => Log.logger.error(err));
        });
        return this.user;
    }

    public signout(): Promise<any> {
        return this.ngZone.runOutsideAngular(() => {
            return this.client.signoutRedirect()
                .catch(err => Log.logger.error(err));
        });
    }

    public signoutCallback(): Promise<any> {
        return this.client.signoutRedirectCallback()
            .catch(err => Log.logger.error(err));
    }

    public authorizationHeader(): Promise<string> {
        return this.ngZone.runOutsideAngular(() => {
            return this.user
                .then(user => user == null ? '' : user.token_type + ' ' + user.access_token);
        });
    }

    public getUser(): Promise<User|null> {
        return this.ngZone.runOutsideAngular(() => {
            return this.user
                .catch(err => Log.logger.error(err));
        });
    }

    public isLoggedIn(debugToken = ''): Promise<boolean> {
        return this.ngZone.runOutsideAngular(() => {
            return this.user.then(user => {
                if (user != null) {
                    return !user.expired;
                }
                return false;
            });
        });
    }

}

У меня были проблемы совместимости между промисами angular2 и oidc-client, поэтому мне пришлось использовать NgZone как видите.

Внедряйте этот сервис везде, где он вам нужен (поле profile поля User содержит ваши утверждения, такие как role, unique_name и т. д.).

Создайте два компонента, такие как LoginComponent и LogoutComponent, которые просто вызывают signinCallback и signoutCallback и перенаправляют куда-нибудь в ваше приложение, например на домашнюю страницу.

@Component({
    selector: 'app-logout',
    templateUrl: './logout.template.html'
})
export class LogoutComponent implements OnInit {
    constructor(private router: Router, private oauthService: OAuthService) { }

    ngOnInit() {
        this.oauthService.signoutCallback().then(() => this.router.navigate(['']));
    }
}

Маршруты этих двух компонентов должны соответствовать заданной конфигурации UserManager в конструкторе OAuthService.

{
    path: 'login',
    component: LoginComponent
},
{
    path: 'logout',
    component: LogoutComponent
},

Например, если redirect_uri равно http://localhost:5000/login, а post_logout_redirect_uri равно http://localhost:5000/login

Вам, вероятно, потребуется подписаться на какое-то событие, чтобы обновить некоторые свойства, когда пользователь просто входит в систему.

public ngOnInit(): void {
    this.onUserChange();
    this.oauthService.events.addUserLoaded(() => this.onUserChange());
    this.oauthService.events.addUserUnloaded(() => this.onUserChange());
}

private onUserChange(): void {
    this.oauthService.isLoggedIn().then(x => this.isLoggedIn = x);
}

После этого вы почти закончили, автоматический вход в систему еще не поддерживается в OpenIddict, и я еще не нашел обходного пути.

Опять же, это все Typescript/Angular2, но его легко адаптировать к JS/Angular.

person Uwy    schedule 19.01.2017
comment
Спасибо большое! Попробую!! /Откровенный - person Frank P; 14.03.2017