OneLogin Python SDK log_user_out()调用返回False问题排查
OneLogin Python SDK
log_user_out() 调用始终返回False问题排查 问题现象
使用OneLogin Python SDK实现用户登出功能时出现异常:传入合法参数调用log_user_out()方法始终返回False,无法完成用户登出,但官方说明方法调用成功时应返回True。
使用完全相同的参数与API凭据通过curl发起请求,可以正常得到成功响应、完成用户登出。
测试过程
Python SDK测试
先通过SDK查询目标用户,提取用户ID传入log_user_out()方法执行登出,方法返回False,浏览器中登录的测试用户初始状态显示未登出;随后提取访问令牌用于后续curl测试,代码执行记录如下:
>>> onelogin_client = OneLoginClient(client_id, client_secret) >>> >>> onelogin_client.get_access_token() <onelogin.api.models.onelogin_token.OneLoginToken object at 0x10e319970> >>> >>> query_parameters = {"email": "aaatestuserbob@eou.edu"} >>> users = onelogin_client.get_users(query_parameters) >>> >>> print(users[0]) User : {'id': 179124057, 'external_id': None, 'email': 'aaatestuserbob@eou.edu', 'username': 'aaatestuserbob@eou.edu', 'firstname': 'Bobby', 'lastname': 'Lasterson', 'distinguished_name': 'redacted', 'phone': None, 'company': '', 'department': '', 'title': '', 'status': 1, 'member_of': '', 'samaccountname': 'aaatestuserbob', 'userprincipalname': '', 'group_id': 442079, 'role_ids': [], 'custom_attributes': {}, 'openid_name': '', 'locale_code': '', 'comment': '', 'directory_id': 50400, 'manager_ad_id': None, 'trusted_idp_id': None, 'manager_user_id': None, 'activated_at': datetime.datetime(2022, 6, 3, 18, 9, 21, 159000, tzinfo=tzutc()), 'created_at': datetime.datetime(2022, 6, 3, 18, 9, 21, 164000, tzinfo=tzutc()), 'updated_at': datetime.datetime(2022, 6, 10, 21, 14, 31, 835000, tzinfo=tzutc()), 'password_changed_at': datetime.datetime(2022, 6, 3, 18, 9, 21, 102000, tzinfo=tzutc()), 'invitation_sent_at': None, 'invalid_login_attempts': 0, 'last_login': datetime.datetime(2022, 6, 10, 21, 14, 31, 580000, tzinfo=tzutc()), 'locked_until': None, 'state': 1} >>> >>> print(users[0].id) 179124057 >>> >>> id = users[0].id >>> >>> onelogin_client.log_user_out(id) False >>> >>> print(onelogin_client.get_access_token()) OneLoginToken : {'access_token': 'redacted_access_token', 'refresh_token': 'redacted_refresh_token', 'account_id': redacted_account_id, 'token_type': 'bearer', 'created_at': datetime.datetime(2022, 6, 13, 15, 4, 33, 753000, tzinfo=tzutc()), 'expires_in': 36000} >>>
curl测试
使用Python测试中完全相同的API凭据发起curl请求,可得到成功响应,测试用户在浏览器中被正常登出,请求如下:
➜ ~ curl 'https://eou.onelogin.com/api/1/users/179124057/logout' \ -X PUT \ -H "Authorization: bearer: redacted_access_token" {"status":{"error":false,"code":200,"type":"success","message":"Success"}}% ➜ ~
补充排查信息
查阅SDK源码后查看客户端错误属性,发现调用时抛出JSONDecodeError异常,错误信息如下:
>>> onelogin_client.error 500 >>> >>> onelogin_client.error_description 'Expecting value: line 1 column 1 (char 0)' >>> >>> onelogin_client.error_attribute >>>
另外注意到SDK默认使用的API地址(eou.onelogin.com)与官方推荐地址(api.us.onelogin.com)不一致,但两个地址通过curl测试均可正常返回成功响应:
➜ ~ curl 'https://api.us.onelogin.com/api/1/users/179124057/logout' \ -X PUT \ -H "Authorization: bearer: redacted_access_token" {"status":{"error":false,"code":200,"type":"success","message":"Success"}}% ➜ ~
问题根因与解决方法
这个问题是OneLogin Python SDK本身的缺陷导致,和传入参数、API凭据配置无关:
- SDK封装的
log_user_out()方法会给所有PUT请求默认添加Content-Type: application/json请求头,但登出接口本身不需要传递任何请求体。当前使用的租户专属域名eou.onelogin.com节点收到带该请求头的空PUT请求时,不会返回约定的JSON格式成功响应,而是直接返回空响应体。SDK尝试将空响应体解析为JSON时就会抛出看到的解码错误,最终直接返回False。 - 看到的
error=500是SDK的错误处理逻辑问题:只要响应解析失败,SDK就会默认将错误码设为500,不代表接口真的返回了500服务错误。实际上第一次调用SDK的log_user_out()方法时,后端大概率已经执行了登出操作,清理浏览器缓存后验证用户登录状态即可确认。 - curl请求能正常执行,是因为手动构造的curl请求没有携带多余的
Content-Type请求头,后端可以正常处理并返回JSON格式的成功响应。
可选择以下任意一种方案修复:
- 初始化
OneLoginClient时,显式指定区域为US,强制SDK使用api.us.onelogin.com作为API端点,该官方节点对空请求体的兼容性更好,会正常返回JSON响应,SDK即可正确解析并返回True。 - 如果不想修改初始化配置,可以跳过SDK封装的
log_user_out()方法,自行构造PUT请求调用登出接口,不要额外添加Content-Type: application/json请求头即可。 - 排查过程中不要反复调用登出接口,哪怕SDK返回
False,第一次调用很可能已经登出成功,重复调用容易触发接口限流。
内容的提问来源于stack exchange,提问作者sbartlett
相关产品推荐
相关产品推荐

