我有一个关于Dart和Flutter中的Oauth2的(可能是?)小问题(我使用的是标准的Oauth2包:https://pub.dev/packages/oauth2)。具体来说,我需要一些作为Authorization流的一部分传回的值,但它们不是标准值,因此它不会作为客户端的一部分返回。
具体地说,作为我的流的一部分,我运行:
final returnValue = await authClient.authenticate(
authorizationUrl: authorizationUrl,
redirectUri: redirectUri!,
);
没问题。然后我跑:
client = await grant
.handleAuthorizationResponse(Uri.parse(returnValue).queryParameters);
同样,正常工作时,返回一个我可以使用的客户端。但是,在此函数之后,handleAuthorizationResponse调用_handleAuthorizationResponse。函数_handleAuthorizationResponse以以下形式结束:
var response =
await _httpClient!.post(tokenEndpoint, headers: headers, body: body);
// print(response.headers);
// print(response.body);
var credentials = handleAccessTokenResponse(
response, tokenEndpoint, startTime, _scopes, _delimiter,
getParameters: _getParameters);
return Client(credentials,
identifier: identifier,
secret: secret,
basicAuth: _basicAuth,
httpClient: _httpClient,
onCredentialsRefreshed: _onCredentialsRefreshed);
这就是我的问题所在。这个响应的主体中有一些我需要的字段。它们不是标准的,所以它们不会作为Client的一部分被传回。在不重写这些函数的情况下,有没有其他方法可以访问这些值?
为了回答一个问题,我们在FHIR上使用了SMART启动(这是一个启动框架,基本上只是一个oauth2 Package 器)--这是医疗保健领域的标准。
{
"need_patient_banner": true,
"smart_style_url": "https://smart.argo.run/smart-style.json",
"patient": "87a339d0-8cae-418e-89c7-8651e6aab3c6",
"token_type": "Bearer",
"scope": "launch/patient patient/Observation.rs patient/Patient.rs",
"expires_in": 3600,
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuZWVkX3BhdGllbnRfYmFubmVyIjp0cnVlLCJzbWFydF9zdHlsZV91cmwiOiJodHRwczovL3NtYXJ0LmFyZ28ucnVuLy9zbWFydC1zdHlsZS5qc29uIiwicGF0aWVudCI6Ijg3YTMzOWQwLThjYWUtNDE4ZS04OWM3LTg2NTFlNmFhYjNjNiIsInRva2VuX3R5cGUiOiJiZWFyZXIiLCJzY29wZSI6ImxhdW5jaC9wYXRpZW50IHBhdGllbnQvT2JzZXJ2YXRpb24ucnMgcGF0aWVudC9QYXRpZW50LnJzIiwiY2xpZW50X2lkIjoiZGVtb19hcHBfd2hhdGV2ZXIiLCJleHBpcmVzX2luIjozNjAwLCJpYXQiOjE2MzM1MzIwMTQsImV4cCI6MTYzMzUzNTYxNH0.PzNw23IZGtBfgpBtbIczthV2hGwanG_eyvthVS8mrG4",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7Im5lZWRfcGF0aWVudF9iYW5uZXIiOnRydWUsInNtYXJ0X3N0eWxlX3VybCI6Imh0dHBzOi8vc21hcnQuYXJnby5ydW4vL3NtYXJ0LXN0eWxlLmpzb24iLCJwYXRpZW50IjoiODdhMzM5ZDAtOGNhZS00MThlLTg5YzctODY1MWU2YWFiM2M2In0sImNsaWVudF9pZCI6ImRlbW9fYXBwX3doYXRldmVyIiwic2NvcGUiOiJsYXVuY2gvcGF0aWVudCBwYXRpZW50L09ic2VydmF0aW9uLnJzIHBhdGllbnQvUGF0aWVudC5ycyBvZmZsaW5lX2FjY2VzcyIsImlhdCI6MTYzMzUzMzg1OSwiZXhwIjoxNjY1MDY5ODU5fQ.Q41QwZCEQlZ16M7YwvYuVbUP03mRFJoqRxL8SS8_ImM"
}
所以它有accessToken的典型值(expires_in,token_type等),但它也有'patient'这样的值,这些都是我需要的值。
在我的示例中,最终的凭据(client.credentials看起来像这样):
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ1cm46b2lkOmZoaXIiLCJjbGllbnRfaWQiOiIzZmE1Y2FmOS04YTk4LTQ4MjgtOTJkZS01OWU2NmJjYjIwNjQiLCJlcGljLmVjaSI6InVybjplcGljOk9wZW4uRXBpYy1jdXJyZW50IiwiZXBpYy5tZXRhZGF0YSI6IjVYWnFRU0lrSk9PNi1XRkhpVXBiMlg2ak5MQzJ1aDFQdWtaSHVWSHkzcTdJMTBBT1BfYXR5V0tEb19LMlRFRF9ic21TNk9UTmZiVGtISnY1dnFvM1RtTVduRlk2RDBPSlE2WkRhd1NJWkk4WDh0Xy1XT1pYWEs1WjFrcTNBNm9mIiwiZXBpYy50b2tlbnR5cGUiOiJhY2Nlc3MiLCJleHAiOjE2NTQ2NDEzMDIsImlhdCI6MTY1NDYzNzcwMiwiaXNzIjoidXJuOm9pZDpmaGlyIiwianRpIjoiMDg1ZTdhNTYtY2I0OS00Zjg3LWFiYmEtZDg0M2ZmODI2YmQ2IiwibmJmIjoxNjU0NjM3NzAyLCJzdWIiOiJlYjRHaWE3RnlpanRQbVhrcnRqUnBQdzMifQ.rAKweImVE86oF3ciZDGhDysrYY9-XV6fBbyzqkQiJxHg-V-zImW414m3X5wKcP9B0J1MMdJCwg5DTpcbd0iU-N3SXRVXxBO2BqTcMAGLr-jlepnqBfu1Esg0nAI9jVasSWhz6tXFcLWOoCocg1hLcMfY875xnszwztJiJieDhumKZSStcsQM4KR9lUQZdJ3-U6IXV7wn3kaD4GQBSPZ0OkUe2d8zdCpjcbGCO-wWNdfe_sQDd7k7MbBJ1ryFRtd45GSzhKFa3Cch8kWTo3bGPlzzFuvhX_kbX1WtqTXaeB2G-o49lT4RJldnZi62L51VtS69_M15EsQtmMRHg6WMEA",
"refreshToken": null,
"idToken": "eyJhbGciOiJSUzI1NiIsImtpZCI6InRvVzlqTVVTTi81L0wzaXdhUUdkVG1ORHVodnAvSmNBWlZIL2NPSjZPckU9IiwidHlwIjoiSldUIn0.eyJhdWQiOiIzZmE1Y2FmOS04YTk4LTQ4MjgtOTJkZS01OWU2NmJjYjIwNjQiLCJleHAiOjE2NTQ2MzgwMDIsImZoaXJVc2VyIjoiaHR0cHM6Ly9maGlyLmVwaWMuY29tL2ludGVyY29ubmVjdC1maGlyLW9hdXRoL2FwaS9GSElSL1I0L1BhdGllbnQvZXJYdUZZVWZ1Y0JaYXJ5VmtzWUVjTWczIiwiaWF0IjoxNjU0NjM3NzAyLCJpc3MiOiJodHRwczovL2ZoaXIuZXBpYy5jb20vaW50ZXJjb25uZWN0LWZoaXItb2F1dGgvb2F1dGgyIiwic3ViIjoiZXJYdUZZVWZ1Y0JaYXJ5VmtzWUVjTWczIn0.hh33_q4f3tnioB7Iq6jY07-m5i_OsaqUt_kg_ZnPMGPKK8AnYVk3Tps2XTdUzUIHizFRWlGmAT_E0F283LBmVPTrbtD_X6EwqmUbTBrWj94RyvE-k3ofoEo-CwbSJZXu8MrQTb3DzpRKTGo7D1sI5E4UqnKQhPWFmhwCjMXpbdRy6bddb14fdWZzjS_Ffq4OsNRIalnePR8z1zNtSy14_RCiSh8o2elkj3p1AOmSXeD9-nZ91Z646lt4C5oP9gwN7OhmBovQRuDYaql1tz1aHOhilIsBZc1jMxEZJ65cekmFy6HZ4rME23xg-EQHu7XhKWOpOjovbMPwapSlC-eUcA",
"tokenEndpoint": "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token",
"scopes": [
"patient/Patient.read",
"patient/Questionnaire.read",
"patient/QuestionnaireResponse.Read",
"fhirUser",
"launch/patient",
"openid",
"profile"
],
"expiration": 1654641291566
}
我尝试过解码accessToken和idToken,但它们都没有“patient”这样的字段。
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ1cm46b2lkOmZoaXIiLCJjbGllbnRfaWQiOiIzZmE1Y2FmOS04YTk4LTQ4MjgtOTJkZS01OWU2NmJjYjIwNjQiLCJlcGljLmVjaSI6InVybjplcGljOk9wZW4uRXBpYy1jdXJyZW50IiwiZXBpYy5tZXRhZGF0YSI6IkJJR1dLcDZPbU1ZcmJkT2YzMkFvX0djRmtiUG1RbEtZcHdEN1d4S0VLNEJXQTZvSUxXVUdRd05SUWdtMUdsd00xTzE0YUVZNi1GTmd6Si1jMGRiQ0puODRIUEU4SDEzNmp6UzNCZGFDUVBMSXFyYXpZenF3Uldyd1MwX3NWU1k5IiwiZXBpYy50b2tlbnR5cGUiOiJhY2Nlc3MiLCJleHAiOjE2NTQ2NDc2MDgsImlhdCI6MTY1NDY0NDAwOCwiaXNzIjoidXJuOm9pZDpmaGlyIiwianRpIjoiMTA1OTFmOTMtYjUxMi00MmNlLTk1YjgtYjY2NTEwODM0MzNkIiwibmJmIjoxNjU0NjQ0MDA4LCJzdWIiOiJlYjRHaWE3RnlpanRQbVhrcnRqUnBQdzMifQ.AJOd9g8YAJp91n0qY3Hg9F2sNpo26VMYKpNKR5y7CIV8zrADh2whv2WRm8gi-cIeS6XUR6UzXyzXVJ9Ips5FgFdIZ4yQI_HXxH9r8aeF6VS6jT-ZQygtzWnVYeyJvu-1b3YpbgdCd3KTrnWLwhU3vqUmil2L8gJzWG473ihXDz-7ezsJBBl9R-c5Ap_L6WF6Ox8lHH6mgwbZHeKr0U0aYne-QLM7mylsPC5BC_WlUOwMnEJ73DKjF2E0X6wMCP7jMieJxhpkTIDRwKQbuGwLjtneS-Efu69NHGsxSP_m3aN652rdh9-b5WyIsT-DqjPHxHTtbxGQI-WthHOhnLaDkQ",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "patient/Patient.read patient/Questionnaire.read patient/QuestionnaireResponse.Read fhirUser launch/patient openid profile",
"__epic.dstu2.patient": "TnOZ.elPXC6zcBNFMcFA7A5KZbYxo2.4T-LylRk4GoW4B",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InRvVzlqTVVTTi81L0wzaXdhUUdkVG1ORHVodnAvSmNBWlZIL2NPSjZPckU9IiwidHlwIjoiSldUIn0.eyJhdWQiOiIzZmE1Y2FmOS04YTk4LTQ4MjgtOTJkZS01OWU2NmJjYjIwNjQiLCJleHAiOjE2NTQ2NDQzMDgsImZoaXJVc2VyIjoiaHR0cHM6Ly9maGlyLmVwaWMuY29tL2ludGVyY29ubmVjdC1maGlyLW9hdXRoL2FwaS9GSElSL1I0L1BhdGllbnQvZXJYdUZZVWZ1Y0JaYXJ5VmtzWUVjTWczIiwiaWF0IjoxNjU0NjQ0MDA4LCJpc3MiOiJodHRwczovL2ZoaXIuZXBpYy5jb20vaW50ZXJjb25uZWN0LWZoaXItb2F1dGgvb2F1dGgyIiwic3ViIjoiZXJYdUZZVWZ1Y0JaYXJ5VmtzWUVjTWczIn0.wxlvguGhAZdWJiSpX1-jzANXk0hFhLeIPFS5BlnIJLLZg8ibvpzLutQr2Z7Rg_d07_amI4gGbNigso9gvPbN5e1jjDGZkU2QYUbcLZbwkTcxXfVWOsyAADOZZrqx0J1yrGIeA4V4EfqQ4xBym_e8CeEjGP9L4ouRBKK6AHR5N5Mmdo_I4_RoPr-mCR2e2Q_of7tYFuhcl8mHaT6brbn-ZoEuAMgAQztF-7SBpDSvRB1C4HzV6mk-Hql0jNhZ0WefZe_ve0gB3exdWDjCLClpRRjt_MRaFTYGPqiZuyJF-dEFEqNar1Y5BRjQmUdJbDWj8ecfWaldigXNVAvNthbs4g",
"patient": "erXuFYUfucBZaryVksYEcMg3"
}
所以你可以理解为什么我需要访问这些信息。除了扩展类和重写函数之外,我还有什么办法可以访问它吗?
2条答案
按热度按时间bfrts1fy1#
access_token
包含响应中的所有信息。访问令牌不应由客户端读取,但ID令牌用于此目的。在身份验证请求中定义正确的作用域也将返回ID令牌。
Client
具有credentials
属性,该属性保存所有令牌。id_token
的sub
字段似乎与patient
匹配,还有fhirUser
用户端点,它可能会给你更多关于病人的信息。vngu2lb82#
所以对于遇到同样问题的人来说,到目前为止我发现答案是你不能从客户端完成它。这是一个从服务器返回的响应的问题。如果你不能访问服务器,你就是SOL,你将不得不使用一个解决方案,比如创建一个代理来发送和接受你所有的查询。
特别是对于我上面的问题,它是服务器不包括以下头
下面是一些其他地方阅读有关CORS的信息,我发现这些信息至少有点帮助:
为跨来源请求设置Cookie
How to solve flutter web api cors error only with dart code?
https://github.com/flutterchina/dio/issues/1027
https://appvesto.medium.com/how-to-add-cors-to-the-dart-server-9d55a2835397