我们利用第三方电子邮件服务提供商(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的声明。
是自定义授权类型的正确用例,还是我们应该寻找不同的方法来实现它?
答案 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."