Description
总结
Citi的portal: https://sandbox.developerhub.citi.com/
几个坑点
- Bluemix上的文档在写Token URL时用了
/oauth2/authorize
, 实际上要写全路径(包含endpoint)才可以, 不然在authorize的时候会报404错误. 其中<API_END_POINT>
的地址, 在Settings > Gateways中可以找到, 比如
https://api.au.apiconnect.ibmcloud.com/orgccs-spacefd/sandbox
还有一个更深的坑, 这个API_END_POINT最后一部分/sandbox
是可以修改的, 值必须和Settings>Overview中的Name保持一致, 不然在authorize的时候也会报404错误
-
任何一个Product都先要在Portal中Subscribe才可使用(只要用到的product都要分别Subscribe), 并且 每个developer自己注册的app,都要分别subscribe.. (共需要点m*n次subscribe) -- Citi的portal消除了这个坑, 完全无需subscribe. 规避方法之一是将所有的API都放在一个product里面, 这样只要订阅一次.
-
Bluemix上的文档在publish product的时候, 每个product里面都包含了两组API, 一组是业务相关的, 一组是OAuth Provider API, 这样在developer订阅了这个product后, 就能使用/token和相应的api服务. 但是每个product里边都要包含一个OAuth Provider API, 是不是太过折腾.我试了一下, 在product中根本不需要包含OAuth Provider API. Citi的做法是, 将authorize和token api单独打包成一个叫Authentication的product, 并publish, 这样developer只要订阅一次这个Authentication的product, 就可以在任意Product里面使用这个auth/token API.
-
直接拿通过client_credentials得到的token,调用受
auth code
保护的API, 竟然也能通过权限认证. 对于这个漏洞, 目前的做法是在后台增加SecurityInterceptor, 从header中取ibm-app-user
, 前一种认证方式ibm api connect会自动将client key放进去, 后一种是自己放入的customer信息. 通过对这个值进行判断, 能得到当前developer传的token的类型. 如果类型不匹配, throw 401 error.
定义和发布API的流程
- 在bluemix中新建API Connect Service(最多只能建一个这样的Service)
- API Connect用catalog来归类不同的环境(比如dev, sit, prod), 默认会建一个叫Sandbox的Catalog, 相当于开发环境.
- 在Catalog > Drafts > APIs中通过API Designer定义API (也可以不使用API Designer直接导入swagger ui生成的json文件
- 对于每个API需要切换到Assemble页面, 定义一个对应的Policy(一般会使用Switch Operation + Invoke或Proxy), Proxy比较实用, 能自动将header, request params, request body原封不动地传给后台的API)
- 到此为止, 可以在Assemble页点那个
▶️ 按钮测试这个API(那个页面有个republish product按钮, 修改了assemble后要点republish product 然后 RUN才会生效). - 之后如果在API Designer中修改了配置, 需要点保存, 然后切到Drafts > Product, 点那个
↑
Stage to Sandbox的按钮 (小心这个按钮会把已经处于publish状态的product变成 stage状态) - stage的下一步必定是切到Dashboard中的Product页面, 点一下publish按钮(折腾)
- 不要乱点🏠, 使用那个
>>
图标切换, 所谓的navigation panel..
一句话: 在Drafts-APIs页面配置API, 在Assemble中做API映射以及测试, 在Drafts-Products-Product页面Stage, 在Dashboard-Products页面Publish.
API Security
在API Designer左边的Security Definition中定义要使用哪种Security(一共有API Key, xx和OAuth)三种, 中间那个叫什么名字, 我忘记了(说明不重要:lol)
同时必定要在API Designer左边的Security中勾选上一个Section中定义的Definition, 又是这种毫无意义的操作.
即stage和publish总是成对出现, Security Definition和Security总是成对出现.
- 我不知道API KEY存在的作用是什么. 估计适用于hello world这样简单的场景, 就是在请求api的时候通过header中传两个固定的key, 分别是Client-ID和Client-Secret.
- 我们不做hello world, 所以只用到了OAuth
添加OAuth 2.0 Provider API
如果要在自定义的API中使用类型为OAuth
的Security Definition, 则必须先添加另外一组内置的API, 名字叫OAuth 2.0 Provider API. 这组内置的API和你自己定义的API有很多相同之处,比如base path, paths, operations. 它在OAuth体系中相当于Authorization Server的角色, 因此它预定了在两个path, 分别是/oauth2/authorize
和/oauth2/token
, 并且规定了各自要求的参数类型(注意第二个Operation: /oauth2/token要求参数必须以Form Data的方式提交).
OAuth 2区块
这个是相比自定义API多出来的一块, 也是最难懂的一块.
Client type
: Public/Confidential(这个选项真的是多此一举,分别对应OAUTH中的2-legged和3-legged)..Scopes
: 对应OAuth中的scope. 比如一个精典的app可以有read, write, delete三种scope. (其它API中的scope必须是这里定义的scopes的子集, 然后在其它自定义API中定义的scope description会覆盖这里写的scope description, 我们的项目并没有区分scope(目前仅定义了一个唯一的scope)Grants
: IBM又一个增加产品复杂度的设定内容, 表示你的Authorization Server支持哪些grant types. 它把OAuth中的Client Credentials叫做Application, 把Authorization Code叫Access Code..你妈, 无谓的多出两个要记的名词. 我们的产品目前使用的grant type是Password.Identity extraction
- Collect credentials using选择Basic, 表示IBM API Connect将会把client传过来的username和password值, 以Basic Auth的方式传给Authentication URL.Authenticate application users using
: 选择Authentication URLAuthentication URL
: 填你的后台API专门做authenticate的API的路径, 只要response code为200, 就表示认证通过, 其它状态码表示认证失败. 可以在你的Authenticate API的response header中添加一个叫``的key. IBM API Connect会把这个key的内容添加到它生成的access_token中. 在它内部解析access_token的时候会把这个值取出来以一个叫ibm-app-user
的值通过request header传给你的API.(妈呀, 文档中只字未提ibm-app-user, 通过在expressjs中打印req.headers我才知道有这么个东西.)
Difference between the “Resource Owner Password Flow” and the “Client Credentials Flow”
使用OAuth Provider API
就是用上面配置的OAuth 2.0 Provider API
来保护你自己的API(需要在你所有的API中都设置一遍), 套路如下:
1. Security Definitions
添加OAuth
,
Name写一个有意义的名字比如OAuth吧 (这个Name会出现在API Product Detail页面上做为帮助文档的一部分)
Flow选择 implicit/password/application/access code之一,
Token URL输入: <API_END_POINT>/<OAUTH2_PROVIDER_API_BASE_PATH>/oauth2/token
Flow必须是在Provider中声明的grants type之一, 我们用的Password.
Scopes: 添加一个或多个当前API用到的Scope, 必须是在Provider中定义的Scopes的子集.
2. Security
勾上上一步创建的OAuth和scope