首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >没有ROPC的Node-Red微软标识平台

没有ROPC的Node-Red微软标识平台
EN

Stack Overflow用户
提问于 2020-10-07 10:34:22
回答 1查看 1.7K关注 0票数 0

是否有一种方法可以使用OAuth 2.0流而不使用Node-Red中的ROPC流来使用微软标识平台?我不能使用ROPC,因为目标租户强制MFA。当MFA被强制执行时,ROPC将被阻塞。

我找到了插件节点-红色-控制-OAuth2,但是除了ROPC之外,它无法与另一个OAuth 2.0流一起使用Microsoft平台。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-13 18:13:58

解决方案是使用设备代码流。下面的说明为您提供了一个流程,它可以读取Microsoft团队的存在状态/MicrosoftOffice365存在状态和节点红色。

在Azure门户中创建应用程序

在下面的示例中,我们将创建一个应用程序,它能够只读取登录用户的存在。这意味着,API权限可能会根据您的需要而有所不同。

  1. 登录Azure门户,转到Azure Active Directory,然后到"App Registartions“,然后单击"+新注册”
  2. 输入一个友好的名称,以帮助识别应用程序。
  3. 支持帐户:仅在此组织目录中的帐户(* -单个租户)
  4. 重定向URI:保留为空,因为我们稍后将设置它。
  5. 点击“注册”
  6. 转到"API权限“。
  7. 删除默认权限,因为它不需要存在。
  8. 单击"+添加权限“。
  9. 点击“微软图形”,然后是“授权权限”。
  10. 选择"offline_access“和"Presence.Read”并使用“添加权限”保存

解释:

  1. 然后,您必须通过单击"+添加权限按钮“旁边的”授予管理许可*"-button来“管理同意这些权限”。
  2. 导航回“概述”并复制“应用程序(客户端) ID”、“目录(租户) ID”的值。
  3. 在导航抽屉中选择“身份验证”。
  4. 点击"+添加平台“
  5. 选择“移动和桌面应用程序”
  6. 选择"https://login.microsoftonline.com/common/oauth2/nativeclient
  7. 提交带有“配置”
  8. 向下滚动到“高级设置”,并在“将应用程序视为公共客户端”旁边选择“是”。并在左上角使用“保存”提交。

现在,这个应用程序可以在Node中使用,用于读取中的内容。

在Node-Red中使用此应用程序

这类流动的一个良好起点是:

代码语言:javascript
复制
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* [{"id":"7c76e545.92af9c","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"40792ca0.843c24","type":"http request","z":"7c76e545.92af9c","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":710,"y":160,"wires":[["44c485e1.fa8d2c","643ed329.5bdfec"]]},{"id":"419648fb.f1a818","type":"inject","z":"7c76e545.92af9c","name":"launch device code request","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":160,"wires":[["427185e9.4132fc"]]},{"id":"657e48c9.bcda48","type":"function","z":"7c76e545.92af9c","name":"Set refresh_token","func":"flow.get('refresh_token', function(err, refresh_token) {\n    if (err) {\n        node.error(err, msg);\n    } else {\n        // initialise the counter to 0 if it doesn't exist already\n        refresh_token = msg.payload.refresh_token;\n        // store the value back\n        flow.set('refresh_token',refresh_token, function(err) {\n            if (err) {\n                node.error(err, msg);\n            } else {\n                // make it part of the outgoing msg object\n                msg.refresh_token = refresh_token;\n                // send the message\n                node.status({fill:\"green\",shape:\"dot\",text:`refresh_token: ${msg.refresh_token}`});\n                node.send(msg);\n            }\n        });\n    }\n});\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":990,"y":340,"wires":[[]]},{"id":"d1253feb.c9362","type":"function","z":"7c76e545.92af9c","name":"Set access_token","func":"flow.get('access_token', function(err, access_token) {\n    if (err) {\n        node.error(err, msg);\n    } else {\n        // initialise the counter to 0 if it doesn't exist already\n        access_token = msg.payload.access_token;\n        // store the value back\n        flow.set('access_token',access_token, function(err) {\n            if (err) {\n                node.error(err, msg);\n            } else {\n                // make it part of the outgoing msg object\n                msg.access_token = access_token;\n                // send the message\n                node.status({fill:\"green\",shape:\"dot\",text:`access_token: ${msg.access_token}`});\n                node.send(msg);\n            }\n        });\n    }\n});\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":990,"y":300,"wires":[[]]},{"id":"44c485e1.fa8d2c","type":"function","z":"7c76e545.92af9c","name":"Set device_code","func":"flow.get('device_code', function(err, refresh_token) {\n    if (err) {\n        node.error(err, msg);\n    } else {\n        // initialise the counter to 0 if it doesn't exist already\n        device_code = msg.payload.device_code;\n        // store the value back\n        flow.set('device_code',device_code, function(err) {\n            if (err) {\n                node.error(err, msg);\n            } else {\n                // make it part of the outgoing msg object\n                msg.device_code = device_code;\n                // send the message\n                node.status({fill:\"green\",shape:\"dot\",text:`device_code: ${msg.device_code}`});\n                node.send(msg);\n            }\n        });\n    }\n});\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":950,"y":160,"wires":[[]]},{"id":"648d5fe3.74d0b","type":"function","z":"7c76e545.92af9c","name":"","func":"var context = flow.get(['tenant_id','client_id','scope','device_code']);\nvar tenant_id = context[0];\nvar client_id = context[1];\nvar scope     = context[2];\nvar device_code = context[3];\n\nif(!device_code)\n{\n    msg.delay = 5*1000;\n    return [msg, null];\n}\n\nif(tenant_id && client_id && scope && device_code)\n{\n    msg.url = \"https://login.microsoftonline.com/\"+tenant_id+\"/oauth2/v2.0/token\";\n    msg.headers = { \"Content-Type\": \"application/x-www-form-urlencoded\"};\n    msg.payload = {\n        \"client_id\": client_id,\n        \"grant_type\": \"urn:ietf:params:oauth:grant-type:device_code\",\n        \"scope\": scope,\n        \"code\": device_code\n    }\n    node.status({fill:\"green\",shape:\"dot\",text:`device_code: ${device_code.substring(0, 10)}`});\n    return [null, msg];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":320,"y":320,"wires":[["ddaa0b36.e42108"],["1fc0a330.6fe22d"]]},{"id":"ec8a6999.9abcd8","type":"inject","z":"7c76e545.92af9c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":320,"wires":[["648d5fe3.74d0b"]]},{"id":"1fc0a330.6fe22d","type":"http request","z":"7c76e545.92af9c","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":510,"y":320,"wires":[["d32c769a.1c42b8"]]},{"id":"ba3c9093.320a7","type":"comment","z":"7c76e545.92af9c","name":"Retrieve tokens ...","info":"... after login has been made in a browser","x":130,"y":260,"wires":[]},{"id":"d4b1dae2.c6c538","type":"comment","z":"7c76e545.92af9c","name":"refresh tokens every 30 minutes","info":"","x":170,"y":400,"wires":[]},{"id":"396bdeb0.93db72","type":"inject","z":"7c76e545.92af9c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1800","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":440,"wires":[["8739bad6.405738"]]},{"id":"8739bad6.405738","type":"function","z":"7c76e545.92af9c","name":"refresh request","func":"var context = flow.get(['tenant_id','client_id','scope','refresh_token']);\nvar tenant_id = context[0];\nvar client_id = context[1];\nvar scope     = context[2];\nvar refresh_token = context[3];\n\nmsg.url = \"https://login.microsoftonline.com/\"+tenant_id+\"/oauth2/v2.0/token\"; \nmsg.headers = {\n    \"Content-Type\": \"application/x-www-form-urlencoded\"\n};\nmsg.payload = {\n        \"grant_type\": \"refresh_token\",\n        \"client_id\": client_id,\n        \"refresh_token\": `${refresh_token}`,\n        \"scope\": scope\n\n};\n\nif(tenant_id && client_id && scope && refresh_token )\n    return msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":340,"y":440,"wires":[["1aafbb4a.e050b5"]]},{"id":"1aafbb4a.e050b5","type":"http request","z":"7c76e545.92af9c","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":550,"y":440,"wires":[["d32c769a.1c42b8"]]},{"id":"97a36414.d2b318","type":"http request","z":"7c76e545.92af9c","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://graph.microsoft.com/beta/me/presence","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":580,"wires":[["cd2de8e1.fdbdd8"]]},{"id":"4a82e18f.d26e","type":"inject","z":"7c76e545.92af9c","name":"","props":[{"p":"payload"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":580,"wires":[["f74a2254.e0487"]]},{"id":"f74a2254.e0487","type":"function","z":"7c76e545.92af9c","name":"","func":"var access_token = flow.get('access_token'); \n\nif(!access_token)\n{\n    node.status({fill:\"blue\",shape:\"dot\",text:`Access token missing. Exiting`});\n    return null;\n}\n\nmsg.headers= {\n            \"Authorization\": \"Bearer \"+access_token\n        };\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":320,"y":580,"wires":[["97a36414.d2b318"]]},{"id":"cd2de8e1.fdbdd8","type":"function","z":"7c76e545.92af9c","name":"","func":"var response = msg.payload;\nif(response.hasOwnProperty('availability') && response.hasOwnProperty('activity'))\n{\n    node.status({fill:\"green\",shape:\"dot\",text:`Status: ${response.availability} (${response.activity})`});\n    return [ { \"payload\": {\n        \"availability\": response.availability,\n        \"activity\": response.activity\n    }}]; \n}\nnode.status({fill:\"red\",shape:\"ring\",text:`Status: some error occurred`});\n\nconsole.log(\"no property availability\");","outputs":1,"noerr":0,"initialize":"","finalize":"","x":700,"y":580,"wires":[[]]},{"id":"8e2a7b69.0d2f38","type":"comment","z":"7c76e545.92af9c","name":"Available Presence Properties","info":"[Docs](https://learn.microsoft.com/en-us/graph/api/resources/presence?view=graph-rest-beta#properties)","x":770,"y":520,"wires":[]},{"id":"b28b4494.18e868","type":"inject","z":"7c76e545.92af9c","name":"change my values","props":[{"p":"scope","v":"Presence.Read offline_access","vt":"str"},{"p":"tenant_id","v":"","vt":"str"},{"p":"client_id","v":"","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"str","x":130,"y":40,"wires":[["4bb4827.9197c7c"]]},{"id":"4bb4827.9197c7c","type":"function","z":"7c76e545.92af9c","name":"prepare context","func":"flow.get('tenant_id', function(err, tenant_id) {\n    if (err) {\n        node.error(err, msg);\n    } else {\n        // store the value\n        flow.set('tenant_id',msg.tenant_id, function(err) {\n            if (err) {\n                node.error(err, msg);\n            } else {\n                flow.get('scope', function(err, scope) {\n                    if (err) {\n                        node.error(err, msg);\n                    } else {\n                        // store the value\n                        flow.set('scope',msg.scope, function(err) {\n                            if (err) {\n                                node.error(err, msg);\n                            } else {\n                                flow.get('client_id', function(err, client_id) {\n                                    if (err) {\n                                        node.error(err, msg);\n                                    } else {\n                                        // store the value\n                                        flow.set('client_id',msg.client_id, function(err) {\n                                            if (err) {\n                                                node.error(err, msg);\n                                            } \n                                            // no else here\n                                        });\n                                    }\n                                });\n                            }\n                        });\n                    }\n                });\n                node.status({fill:\"green\",shape:\"dot\",text:`OK: context prepared`});\n            }\n        });\n    }\n});","outputs":1,"noerr":0,"initialize":"","finalize":"","x":360,"y":40,"wires":[[]]},{"id":"427185e9.4132fc","type":"function","z":"7c76e545.92af9c","name":"prepare device code request","func":"msg.headers = { \"Content-Type\": \"application/x-www-form-urlencoded\"};\n\nvar context = flow.get(['tenant_id','client_id','scope']);\nvar tenant_id = context[0];\nvar client_id = context[1];\nvar scope     = context[2];\nif(tenant_id && client_id && scope)\n{\n    msg.url = \"https://login.microsoftonline.com/\"+tenant_id+\"/oauth2/v2.0/devicecode\"\n    msg.payload = {    \n        \"client_id\": client_id,\n        \"scope\": scope\n    };\n    node.status({fill:\"green\",shape:\"dot\",text:`Values passed on`});\n    return msg;\n}\n\nnode.status({fill:\"red\",shape:\"dot\",text:`ERROR: context not prepared`});","outputs":1,"noerr":0,"initialize":"","finalize":"","x":460,"y":160,"wires":[["40792ca0.843c24"]]},{"id":"ddaa0b36.e42108","type":"delay","z":"7c76e545.92af9c","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":520,"y":240,"wires":[["648d5fe3.74d0b"]]},{"id":"d32c769a.1c42b8","type":"function","z":"7c76e545.92af9c","name":"","func":"var context = flow.get(['access_token','refresh_token']);\nvar access_token  = context[0]; \nvar refresh_token = context[1]; \n\nif(msg.payload.hasOwnProperty('access_token') && \nmsg.payload.hasOwnProperty('refresh_token'))\n{\n    flow.set('device_code',undefined);\n    node.status({fill:\"green\",shape:\"dot\",text:`device now logged in, pass on message`});\n    return [null, msg];     \n}\n\n\nif(access_token && refresh_token)\n{\n    flow.set('device_code',undefined);\n    node.status({fill:\"green\",shape:\"dot\",text:`device already logged in`});\n    return [];\n}\n\nif(msg.payload.hasOwnProperty('error'))\n{\n    if(msg.payload.error == \"authorization_pending\")\n    {\n        node.status({fill:\"blue\",shape:\"dot\",text:`Browser login pending`});\n        msg.delay = 5*1000;\n        return [msg, null]; \n    }\n    node.status({fill:\"red\",shape:\"dot\",text:`Error: ${msg.payload.error_description}`});\n    return [];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":740,"y":320,"wires":[["ddaa0b36.e42108"],["d1253feb.c9362","657e48c9.bcda48"]]},{"id":"643ed329.5bdfec","type":"debug","z":"7c76e545.92af9c","name":"Auth link and device code","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":980,"y":100,"wires":[]},{"id":"2347386d.7321d8","type":"comment","z":"7c76e545.92af9c","name":"MS Graph request (presence)","info":"[Docs](https://learn.microsoft.com/en-us/graph/api/resources/presence?view=graph-rest-beta#properties)","x":190,"y":520,"wires":[]}]
*/

这将为您提供以下流程,它可以读取Microsoft团队的存在状态/MicrosoftOffice365存在状态和节点红色:

  1. 双击“更改我的值”-node并输入client_id、tenant_id和使用的范围。读取呈现的作用域默认值已经设置。
  2. 部署节点。
  3. 启动“启动设备代码请求”。
  4. 在调试控制台中,您将得到一个代码,您应该在任何设备上的浏览器中复制和打开给定的链接。
  5. 在浏览器中执行身份验证过程,直到它显示登录成功,并且可以关闭该浏览器窗口。
  6. 接下来,单击“检索令牌”下的注入节点。
  7. 如果右边的节点显示绿色值,一切都是成功的,那么您就可以开始了。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64242252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档