Cam*_*ron 47 javascript oauth-2.0
我目前正在尝试使用OAuth2开发一个完全用JavaScript构建的移动应用程序,该应用程序与CakePHP API进行通信.看看下面的代码,看看我的应用程序当前的外观(请注意,这是一个实验,因此代码混乱,缺乏结构区域等等.)
var access_token,
refresh_token;
var App = {
init: function() {
$(document).ready(function(){
Users.checkAuthenticated();
});
}(),
splash: function() {
var contentLogin = '<input id="Username" type="text"> <input id="Password" type="password"> <button id="login">Log in</button>';
$('#app').html(contentLogin);
},
home: function() {
var contentHome = '<h1>Welcome</h1> <a id="logout">Log out</a>';
$('#app').html(contentHome);
}
};
var Users = {
init: function(){
$(document).ready(function() {
$('#login').live('click', function(e){
e.preventDefault();
Users.login();
});
$('#logout').live('click', function(e){
e.preventDefault();
Users.logout();
});
});
}(),
checkAuthenticated: function() {
access_token = window.localStorage.getItem('access_token');
if( access_token == null ) {
App.splash();
}
else {
Users.checkTokenValid(access_token);
}
},
checkTokenValid: function(access_token){
$.ajax({
type: 'GET',
url: 'http://domain.com/api/oauth/userinfo',
data: {
access_token: access_token
},
dataType: 'jsonp',
success: function(data) {
console.log('success');
if( data.error ) {
refresh_token = window.localStorage.getItem('refresh_token');
if( refresh_token == null ) {
App.splash();
} else {
Users.refreshToken(refresh_token);
}
} else {
App.home();
}
},
error: function(a,b,c) {
console.log('error');
console.log(a,b,c);
refresh_token = window.localStorage.getItem('refresh_token');
if( refresh_token == null ) {
App.splash();
} else {
Users.refreshToken(refresh_token);
}
}
});
},
refreshToken: function(refreshToken){
$.ajax({
type: 'GET',
url: 'http://domain.com/api/oauth/token',
data: {
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: 'NTEzN2FjNzZlYzU4ZGM2'
},
dataType: 'jsonp',
success: function(data) {
if( data.error ) {
alert(data.error);
} else {
window.localStorage.setItem('access_token', data.access_token);
window.localStorage.setItem('refresh_token', data.refresh_token);
access_token = window.localStorage.getItem('access_token');
refresh_token = window.localStorage.getItem('refresh_token');
App.home();
}
},
error: function(a,b,c) {
console.log(a,b,c);
}
});
},
login: function() {
$.ajax({
type: 'GET',
url: 'http://domain.com/api/oauth/token',
data: {
grant_type: 'password',
username: $('#Username').val(),
password: $('#Password').val(),
client_id: 'NTEzN2FjNzZlYzU4ZGM2'
},
dataType: 'jsonp',
success: function(data) {
if( data.error ) {
alert(data.error);
} else {
window.localStorage.setItem('access_token', data.access_token);
window.localStorage.setItem('refresh_token', data.refresh_token);
access_token = window.localStorage.getItem('access_token');
refresh_token = window.localStorage.getItem('refresh_token');
App.home();
}
},
error: function(a,b,c) {
console.log(a,b,c);
}
});
},
logout: function() {
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
access_token = window.localStorage.getItem('access_token');
refresh_token = window.localStorage.getItem('refresh_token');
App.splash();
}
};
Run Code Online (Sandbox Code Playgroud)
我有很多与OAuth实施有关的问题:
1.)显然将access_token存储在localStorage中是不好的做法,我应该使用cookie.有谁能解释为什么?因为这不是更安全或更不安全,因为cookie数据不会被加密.
更新:根据这个问题:本地存储与存储localStorage中的数据的Cookie仅在客户端可用,并且不像cookie那样做任何HTTP请求,所以对我来说似乎更安全,或者至少似乎没有据我所知,有任何问题!
2.)与问题1相关,使用cookie到期时间对我来说同样毫无意义,就好像你查看代码一样,在app上发出请求以获取用户信息,如果查询,则会返回错误它已在服务器端过期,并需要refresh_token.所以不确定在BOTH客户端和服务器上有到期时间的好处,当服务器真正重要时.
3.)如何在没有A的情况下获取刷新令牌,将其与原始access_token一起存储以供以后使用,以及B)还存储client_id?我被告知这是一个安全问题,但我怎样才能在以后使用它们,但是在仅限JS的应用程序中保护它们?再次看到上面的代码,看看到目前为止我是如何实现的.
jan*_*sen 82
看起来您正在使用资源所有者密码凭据 OAuth 2.0流程,例如,提交用户名/密码以获取访问令牌和刷新令牌.
考虑到这一背景,让我来解答你的问题:
http://domain.com/api/oauth/token,并接收访问令牌和刷新令牌.不可否认,这确实违反了您所寻求的"仅限JS"约束.但是,a)你真的不应该在javascript中有一个刷新令牌,而b)它在登录/注销时需要非常小的服务器端逻辑,并且没有持久的服务器端存储.
关于CSRF的说明:如评论中所述,此解决方案不涉及跨站点请求伪造 ; 请参阅OWASP CSRF预防备忘单,了解有关解决这些攻击形式的更多想法.
另一个替代方法是根本不要求刷新令牌(不确定这是否是您正在处理的OAuth 2实现的选项;刷新令牌根据规范是可选的)并在其到期时不断重新进行身份验证.
希望有所帮助!
完全安全的唯一方法是不存储客户端的访问令牌。任何能够(物理)访问您的浏览器的人都可以获取您的令牌。
您对这两者都不是一个好的解决方案的评估是准确的。
如果您仅限于客户端开发,那么使用过期时间是最好的选择。它不需要您的用户频繁地使用 Oauth 重新进行身份验证,并保证令牌不会永远存在。仍然不是最安全的。
获取新令牌需要执行 Oauth 工作流程来获取新令牌。client_id 与 Oauth 运行的特定域绑定。
保留 Oauth 令牌的最安全方法是服务器端实现。
| 归档时间: |
|
| 查看次数: |
26435 次 |
| 最近记录: |