限制访问单个资源的Oauth2令牌

时间:2016-06-13 08:13:02

标签: security authentication claims-based-identity identityserver3 oauth2

我们利用第三方电子邮件服务提供商(ESP)向我们的客户发送电子邮件。其中一封电子邮件需要附加一个文件。为此,我们需要为ESP提供该文件的URL。 ESP将下载该文件并将其附加到电子邮件中。

我们正在制定解决方案以保护网址,以限制未经授权下载的风险。 ESP在向URL发出请求时无法对自身进行身份验证,因此我们看到的唯一选择是难以猜测URL并使其在有限时间内有效。

我们想要实现此目的的方法是在URL的查询字符串中添加一个标记。托管该文件的服务将验证令牌并授权访问。令牌需要及时过期,并且只能访问特定文件。

我们已经有一个运行oAuth2安全令牌服务的IdentityServer 3实现。我们的计划是让这个服务生成将放在文件下载URL的查询字符串中的标记。我们正在考虑创建一个自定义oAuth2授权类型来支持只允许访问特定资源的令牌。

这是使用自定义授权向oauth2令牌端点发出请求的示例:

 POST /token HTTP/1.1
 Host: server.example.com
 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
 Content-Type: application/x-www-form-urlencoded

 grant_type=custom_grant&scope=attachment.read&resource_id=xxxxx

STS将返回一个令牌,其中包含令牌可以访问的资源ID的声明。

是自定义授权类型的正确用例,还是我们应该寻找不同的方法来实现它?

1 个答案:

答案 0 :(得分:0)

我认为你提出的建议很好,但我个人更喜欢使用基于加密签名的东西来做这类事情。

JSON Web Token是一种成熟的方法,可以在许多编程语言中提供支持。基本上,您签署一个JSON字典,包括到期时间。然后将其附加到URL(例如,作为查询参数)。收到入站请求时,您可以通过检查签名,到期时间以及它应用的资源来验证令牌。

这种方法的优势在于没有不必要的状态:您不必在任何地方存储令牌,而只需要签名密钥。

这是Python中的一个示例,它显示了基本概念:

import time

import jwt

SIGNING_SECRET = 'use-a-good-secret-here'

token = jwt.encode({
    'resource_id': 'xxxxx',
    # JSON spec establishes "exp" as meaning expiration time
    'exp': time.time() + 1, # one second in the future for testing
}, SIGNING_SECRET, algorithm='HS256')

print(token)

def try_decoding(token):
    try:
        decoded = jwt.decode(token, SIGNING_SECRET, algorithms=['HS256'])
        print('Valid token for "{}"'.format(decoded['resource_id']))
    except jwt.exceptions.ExpiredSignatureError:
        print('The token has expired.')

try_decoding(token) # prints 'Valid token for "xxxxx"'
print('Sleeping until the token expires...')
time.sleep(2)
try_decoding(token) # prints "The token has expired."