Oauth 2 popup with Angular 2
Oauth 2 popup with Angular 2
我正在升级/重写现有的angular应用程序以使用angular2。我的问题是,我想在一个新的弹出窗口中打开一个OAuth流,一旦OAuth流程完成,就使用window.postMessage向angular 2应用程序传达OAuth流量成功的消息。
目前我所拥有的是角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
似乎完全打破了angular 2应用程序,取消了对this
的引用。
所以我的问题是,我可以使用window.addEventListener吗?还是不应该使用postMessage与angular2应用程序进行通信?
**完成angular 2 noob,因此任何帮助都将受到感谢
我在Github上有一个完整的Angular2 OAuth2骨架应用程序,您可以参考。
它使用Auth服务进行OAuth2隐式授权,然后使用Window服务创建弹出窗口。然后,它监视该窗口中URL上的访问令牌。
您可以在此处访问演示OAuth2 Angular代码(使用Webpack)。
以下是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);
}
如果您在启动和运行应用程序时有任何问题,请随时询问。
所以经过一点调查发现了问题。我正在取消引用this
。这个githubwiki帮助我对它有了更多的理解。
为了解决我的案子,需要做几件事。首先,我创建了一个服务,该服务封装了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
}
然后它按照我期望的方式工作,保留对这个的引用
我认为这是Angular2方式:
(Dart代码,但TS应该非常相似)
@Injectable()
class SomeService {
DomAdapter dom;
SomeService(this.dom) {
dom.getGlobalEventTarget('window').addEventListener("message", fn, false);
}
}
我花了很长时间才这么做,但最终,对我来说,最稳健的方法是将用户重定向到宣誓页面
window.location.href = '/auth/logintwitter';
在后台进行宣誓舞(我使用了express),然后重定向回接收前端页面。。。
res.redirect(`/#/account/twitterReturn?userName=${userName}&token=${token}`);
我的解决方案有一些特殊之处,因为例如,无论登录类型如何,我都只想在客户端上使用JsonWebToken,但如果您感兴趣,整个解决方案都在这里。
https://github.com/JavascriptMick/learntree.org
- Angular 2.0 with JavaScript or TypeScript?
- Angular $injector:unpr with uibModal
- Bootstrap scrollspy with angular-ui
- Angular with Browserify
- JavaScript array.push (object) with Angular ng-repeat 无法按预期运
- Google Analytics with SPA (Angular.js)
- angular.forEach with .find
- getting confused with firebase,angular, node js
- Angular JS ng-switch with ng-include?
- Nested Views with Dynamic Id's Angular & Rails
- 在 angular.js 中,没有 () 的函数调用与调用 with() 有什么不同吗?
- Angular JS & CSRF with RESTFull API Laravel
- Angular.js integration with Ruby On Rails Forms
- jQuery key event with angular
- Angular with multiples $anchorScroll
- Angular with Node
- Angular with hapi js server jsonp
- 单元测试Angular with Breeze
- Angular with jquery
- 如何将单选按钮标记为选中Angular with ng click/ng change