2016-01-05 5 views
4

Я обновляю/переписываю существующее угловое приложение для использования углового2. Моя проблема заключается в том, что я хочу открыть поток OAuth в новом всплывающем окне, и как только поток OAuth будет завершен, используйте window.postMessage для обратной связи с угловым 2, что поток OAuth был успешным.Oauth 2 popup with Angular 2

В настоящее время, что я имею в угловом 2 сервиса

export class ApiService { 
    constructor(private _loggedInService: LoggedInService) { 
     window.addEventListener('message', this.onPostMessage, false); 
    } 

    startOAuthFlow() { 
     var options = 'left=100,top=10,width=400,height=500'; 
     window.open('http://site/connect-auth', , options); 
    } 

    onPostMessage(event) { 
     if(event.data.status === "200") { 
      // Use an EventEmitter to notify the other components that user logged in 
      this._loggedInService.Stream.emit(null); 
     } 
    } 

} 

Этот шаблон, который загружается в конце OAuth потока

<html> 
    <head> 
    <title>OAuth callback</title> 
    <script> 
     var POST_ORIGIN_URI = 'localhost:8000'; 
     var message = {"status": "200", "jwt":"2"}; 
     window.opener.postMessage(message, POST_ORIGIN_URI); 
     window.close(); 
    </script> 
    </head> 
</html> 

Использование window.addEventListener, как это, кажется, полностью разорвать угловое приложение 2, разыменование this.

Так что мой вопрос в том, могу ли я использовать window.addEventListener, или я не должен использовать postMessage для связи обратно в приложение angular2?

** Полный angular2 нуба так что любая помощь ценится

ответ

2

Так что с небольшим количеством расследований выяснилось, что проблема. Я отказался от ссылки this. Этот github wiki помог мне понять это немного больше.

Для решения этого вопроса необходимо сделать пару вещей. Во-первых, я создал службу, инкапсулированный добавление к EventListener

import {BrowserDomAdapter} from 'angular2/platform/browser'; 

export class PostMessageService { 
    dom = new BrowserDomAdapter(); 
    addPostMessageListener(fn: EventListener): void { 
    this.dom.getGlobalEventTarget('window').addEventListener('message', fn,false) 
    } 
} 

Затем с помощью этого addPostMessageListener я могу прикрепить функцию в моей другой службе стрелять

constructor(public _postMessageService: PostMessageService, 
    public _router: Router) { 
    // Set up a Post Message Listener 
    this._postMessageService.addPostMessageListener((event) => 
      this.onPostMessage(event)); // This is the important as it means I keep the reference to this 

} 

Затем он работает, как я ожидал, сохраняя ссылку к этому

+0

любая идея, как это можно сделать теперь, когда 'BrowserDomAdapter' больше не экспортируется в угловые 2 RC? – simon

+0

update: на самом деле вы можете просто использовать 'window.addEventListener' - важная часть, как вы указываете, использует анонимную функцию для сохранения контекста выполнения. Благодаря! – simon

+0

Здравствуйте, возможно ли, что если получать сообщение с того же компьютера, но с другим портом? Я хочу отправить данные из моего jsp/java (порт 8080) в angular2 listener (порт 4200). –

1

Я думаю, что это Angular2 путь:

(Dart код, но TS должен быть очень похож)

@Injectable() 
class SomeService { 
    DomAdapter dom; 
    SomeService(this.dom) { 
    dom.getGlobalEventTarget('window').addEventListener("message", fn, false); 
    } 
} 
+0

Благодаря этим помогло мне добраться до моего решения! – royka

5

I имеют полное скелет Angular2 OAuth2 на Github, к которому вы можете обратиться.

Он использует службу Auth для OAuth2 Неявные гранты, которые, в свою очередь, используют службу Window для создания всплывающего окна. Затем он отслеживает это окно для токена доступа по URL-адресу.

Доступ к demo OAuth2 Angular code (with Webpack) here.

Здесь находится процедура входа в систему от службы Auth, которая даст вам представление о том, что происходит, без необходимости просмотра всего проекта. Я добавил несколько дополнительных комментариев для вас.

public doLogin() { 
    var loopCount = this.loopCount; 
    this.windowHandle = this.windows.createWindow(this.oAuthTokenUrl, 'OAuth2 Login'); 

    this.intervalId = setInterval(() => { 
     if (loopCount-- < 0) { // if we get below 0, it's a timeout and we close the window 
      clearInterval(this.intervalId); 
      this.emitAuthStatus(false); 
      this.windowHandle.close(); 
     } else { // otherwise we check the URL of the window 
      var href:string; 
      try { 
       href = this.windowHandle.location.href; 
      } catch (e) { 
       //console.log('Error:', e); 
      } 
      if (href != null) { // if the URL is not null 
       var re = /access_token=(.*)/; 
       var found = href.match(re); 
       if (found) { // and if the URL has an access token then process the URL for access token and expiration time 
        console.log("Callback URL:", href); 
        clearInterval(this.intervalId); 
        var parsed = this.parse(href.substr(this.oAuthCallbackUrl.length + 1)); 
        var expiresSeconds = Number(parsed.expires_in) || 1800; 

        this.token = parsed.access_token; 
        if (this.token) { 
         this.authenticated = true; 
        } 

        this.startExpiresTimer(expiresSeconds); 
        this.expires = new Date(); 
        this.expires = this.expires.setSeconds(this.expires.getSeconds() + expiresSeconds); 

        this.windowHandle.close(); 
        this.emitAuthStatus(true); 
        this.fetchUserInfo(); 
       } 
      } 
     } 
    }, this.intervalLength); 
} 

Не стесняйтесь спрашивать, есть ли у вас какие-либо вопросы или проблемы с запуском приложения.