Oauth 2 popup with Angular 2

I am updating / rewriting an existing angular application to use angular2. My problem is that I want to open the OAuth stream in a new popup, and once the OAuth stream has completed, use window.postMessage to contact the angular 2 application that the OAuth stream was successful.

I currently have an angular 2 service

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); } } } 

This template, which is loaded at the end of the OAuth stream

 <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> 

Using window.addEventListener similar seems to completely break the angular 2 application, dereference this .

So my question is: can I use window.addEventListener or not use postMessage to communicate with the angular2 application?

** Complete angular2 noob, so any help would be appreciated

+5
source share
4 answers

So, with a small number of investigations, the problem turned out. I refused the this link. This github wiki helped me figure this out a bit more.

To solve this for my case, you need to do a couple of things. First, I created a service that encapsulated the addition of 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) } } 

Then, using this addPostMessageListener , I can connect a function in my other service to run

 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 } 

Then it works as I expected a link to this

+2
source

I have a complete skeleton Angular2 OAuth2 application on Github that you can refer to.

It uses the Auth service for implicit grants of OAuth2, which in turn uses the Window service to create a popup. He then monitors this window for the access token at the URL.

Here you can get the OAuth2 Angular demo code (using Webpack) .

Here is the procedure for logging in from the Auth service, which will give you an idea of ​​what is happening without having to look at the entire project. I have added some additional comments for you.

 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 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); } 

Feel free to ask if you have any questions or problems starting the application.

+5
source

I think this is Angular2's way:

(Dart code, but TS should be very similar)

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

OAuth popup example I was described to hire

0
source

Source: https://habr.com/ru/post/1239914/


All Articles