Application User Roles with Azure B2C

The Pragmatic Programmer
15 Nov 202226:15

Summary

TLDR本视频教程介绍了如何在Azure B2C中使用API连接器来实现用户角色和权限管理。尽管Azure B2C本身不支持用户角色,但通过API连接器,我们可以在身份验证过程中添加自定义声明,实现不同用户访问不同应用部分的功能。视频详细演示了如何开发本地API连接器,设置反向代理以及在Azure B2C中配置API连接器。此外,还展示了如何在前端和后端应用中利用这些角色信息来控制用户访问权限。

Takeaways

  • 😀 使用Azure B2C的API连接器可以实现用户角色的自定义,从而控制用户访问应用程序或后端API的不同部分。
  • 🔒 Azure B2C本身不支持开箱即用的用户角色,但可以通过API连接器来实现角色控制。
  • 🌐 API连接器允许Azure B2C在用户认证过程中调用外部API,以添加额外的声明(claims)到用户凭证中。
  • 🔑 被调用的API必须是公开可访问的HTTPS端点,并且需要有证书支持。
  • 🛠️ 开发者可以通过设置反向代理函数,使得本地开发环境能够模拟API连接器的行为,便于本地开发和测试。
  • 🏠 在本地开发时,可以通过端口转发将本地Azure函数暴露到互联网上,并通过反向代理与Azure B2C通信。
  • 📝 在Azure门户中设置API连接器时,需要指定Azure函数的URL和要调用的特定函数,如用户权限函数。
  • 🔄 部署到生产环境时,需要重新配置Azure B2C,使其直接调用已发布的API函数,以添加自定义声明。
  • 🔑 在Next.js应用中,可以通过检查ID令牌中的自定义声明来控制用户界面的显示,如仅对具有管理员角色的用户显示管理员链接。
  • 🛡️ 在API层面,可以通过中间件检查访问令牌中的用户角色,以限制对特定Azure函数的访问,确保只有具有相应角色的用户才能调用。

Q & A

  • Azure B2C是否原生支持用户角色功能?

    -Azure B2C原生并不支持用户角色功能,但可以通过API连接器来实现类似功能。

  • API连接器在Azure B2C中的作用是什么?

    -API连接器允许Azure B2C在用户认证过程中调用外部API,该API可以添加额外的声明(claims),这些声明随后会被注入到用户的令牌中。

  • API连接器调用的API有哪些要求?

    -API连接器调用的API必须是公共端点,并且是HTTPS端点,即需要有证书安装。

  • 如何在本地开发环境中使用API连接器?

    -可以通过设置反向代理功能,将本地开发机器暴露到互联网上,使得Azure B2C能够调用本地API连接器。

  • 如何将本地Azure函数暴露到互联网上?

    -可以通过路由器的端口转发功能,将本地Azure函数运行的内部IP地址和端口转发到外部端口。

  • 创建Azure函数的反向代理时需要注意什么?

    -需要配置反向代理函数以接受要代理到的函数名称作为URL的查询参数,并确保正确设置了代理API主机的环境变量。

  • 如何在Azure门户中设置API连接器?

    -需要在Azure门户中找到API连接器选项,添加新的API连接器,并配置其指向正确的Azure函数以及必要的安全凭证。

  • 如何在用户流程中使用API连接器?

    -在用户流程中,需要在API连接器部分选择之前设置的API连接器,并在应用声明中添加自定义声明,以便在用户登录过程中调用API连接器。

  • 如何在Next.js应用中利用用户角色信息?

    -可以在Next.js的用户存储中添加一个方法来检查用户是否具有特定的权限,然后在UI组件中根据用户角色显示或隐藏相应的链接。

  • 如何在Azure函数API中实现基于角色的授权?

    -可以在Azure函数的授权中间件中添加对用户角色的检查,确保调用者具有正确的角色和权限范围。

Outlines

00:00

🔒 使用Azure B2C实现用户角色和权限管理

本段介绍了如何使用Azure B2C的用户角色功能来管理不同用户的权限,以便他们可以访问应用程序或后端API的不同部分。尽管Azure B2C官方不支持开箱即用的用户角色,但可以通过API连接器实现。API连接器允许Azure B2C在用户认证过程中调用外部API,以添加额外的声明(claims)到用户的凭证中。视频还讨论了开发本地化时如何使用反向代理功能,以及如何将这些功能部署到生产环境。

05:00

🛠️ 构建本地开发环境的反向代理

这一段详细说明了如何设置本地开发环境中的反向代理,以便可以从互联网访问Azure函数。介绍了如何通过路由器设置端口转发,以及如何在Visual Studio Code中创建一个新的Azure函数来作为反向代理。这个代理将捕获对特定函数的调用,并将请求转发到本地开发机器上的对应API,然后再将响应返回给Azure B2C。

10:02

📝 创建API连接器以添加用户权限

本段讲述了如何创建一个名为'user permissions'的Azure函数,该函数通过接收POST请求来添加用户自定义权限。函数首先检查请求体是否正确反序列化,然后根据用户的身份验证信息添加相应的权限声明。此外,还介绍了如何在Azure门户中配置API连接器,以及如何将自定义属性添加到用户流中。

15:03

🔄 测试和部署API连接器

在这一段中,演示了如何测试和部署API连接器。通过在Azure门户中设置新的API连接器,并将其链接到之前创建的'user permissions' Azure函数。接着,介绍了如何在用户流中添加自定义声明,以及如何在应用程序中使用这些声明来控制对API的访问。

20:06

🏢 应用用户角色于前端和后端

本段讨论了如何在应用程序的前端和后端实现用户角色的应用。在前端,展示了如何根据用户的角色来显示或隐藏UI元素。在后端,介绍了如何修改API的授权中间件,以确保只有具有适当角色的用户才能访问特定的API端点。

25:09

👍 结束语和用户角色的保护

视频的最后一段是对如何使用Azure B2C实现用户角色和权限管理的总结。展示了如何测试前端和后端的用户角色保护,并鼓励观众如果发现视频有用,请点赞支持。最后,感谢观众的观看,并预告了下一个视频的内容。

Mindmap

Keywords

💡Azure B2C

Azure B2C是微软Azure提供的一套身份认证服务,允许开发者轻松地将用户认证功能集成到应用程序中。在视频中,Azure B2C用于处理用户角色和权限管理,通过API连接器实现自定义的用户角色验证。

💡用户角色

用户角色是权限管理中的一个概念,用于区分不同用户可以访问的资源和执行的操作。视频中讲解了如何在Azure B2C中通过API连接器实现用户角色的自定义和应用。

💡API连接器

API连接器是Azure B2C的一个功能,允许Azure B2C在用户认证过程中调用外部API。视频中提到,通过API连接器可以添加额外的声明(claims),从而实现用户角色的自定义。

💡HTTPs端点

HTTPs端点是指使用安全套接字层(SSL)加密的网络服务端点,保证了数据传输的安全性。视频中提到API连接器必须调用具有证书的公共HTTPs端点。

💡自定义声明

自定义声明是向用户认证令牌中添加的额外信息,可以包含任何自定义数据。视频中通过API连接器向Azure B2C添加自定义声明,用于用户角色的标识。

💡反向代理

反向代理是一种网络服务,可以将客户端的请求转发到内部或外部的服务器。视频中使用反向代理将本地开发环境暴露到互联网上,以便Azure B2C可以访问本地API。

💡本地开发

本地开发指的是开发者在个人计算机上进行的程序开发工作。视频中讨论了如何在本地开发环境中设置API连接器,以便在开发过程中测试和验证用户角色和权限。

💡访问令牌

访问令牌是用户认证成功后颁发的一种凭证,允许用户访问特定的资源或服务。视频中提到,自定义声明被注入到访问令牌中,使得前端应用可以读取用户的角色信息。

💡JWT

JWT(JSON Web Token)是一种用于在网络应用环境间传递声明的一种紧凑的、URL安全的方式。视频中提到使用jwt.ms来查看访问令牌和ID令牌中的声明内容。

💡权限验证

权限验证是检查用户是否有权执行特定操作或访问特定资源的过程。视频中展示了如何在前端和后端应用中使用用户角色信息进行权限验证。

Highlights

使用Azure B2C API连接器实现用户角色和权限管理。

Azure B2C不支持开箱即用的用户角色,但可通过API连接器实现。

API连接器允许Azure B2C在身份验证过程中调用外部API,以添加额外的声明。

API必须为公共端点,并使用HTTPS协议。

介绍了如何在本地开发环境中使用反向代理功能来模拟API连接器。

通过反向代理,可以在本地开发时模拟Azure环境中的API连接器行为。

展示了如何在Visual Studio Code中设置和测试反向代理Azure函数。

解释了如何在Azure门户中配置反向代理的API主机环境变量。

演示了如何将本地开发的API连接器功能发布到Azure。

讨论了如何在Azure B2C中添加和配置API连接器。

介绍了如何在用户流程中添加自定义属性以使用API连接器返回的数据。

展示了如何在Azure函数中编写代码以根据用户角色添加自定义声明。

解释了如何在Next.js应用程序中使用用户角色数据来控制UI元素的显示。

演示了如何在API中使用用户角色数据来限制对特定端点的访问。

讨论了如何在生产环境中移除反向代理并直接调用添加了声明的API。

强调了用户角色和权限管理在保护Web应用和API安全中的重要性。

提供了如何在不同环境(开发、生产)中灵活配置API连接器的指导。

总结了使用Azure B2C API连接器实现用户角色和权限管理的整个流程。

Transcripts

play00:00

if you want logged in users of your

play00:02

website to have different permissions so

play00:04

that they can access different parts of

play00:06

your application or even your backend

play00:08

API then you've come to the right place

play00:10

because today we are going to be dealing

play00:12

with user roles with azure b2c

play00:16

[Music]

play00:16

[Applause]

play00:21

good morning good afternoon and good

play00:23

evening whenever it is I find you and

play00:25

welcome along to the channel so if you

play00:27

Google for Azure b2c and user roles

play00:30

you'll find generally a whole lot of

play00:33

negativity around things that it says it

play00:36

doesn't support user roles out of the

play00:39

box

play00:40

and while that's true there is a

play00:43

mechanism in Azure b2c that we can

play00:46

utilize for this purpose and that is API

play00:49

connectors so what are API connectors so

play00:53

the way that Azure b2c works is our

play00:55

authenticating user goes across to or

play00:58

gets redirected to azure b2c

play01:01

Azure b2c can then call out to an API so

play01:06

this API has got some constraints it

play01:08

must be a public endpoint and it must

play01:10

also be an HTTP s endpoint so it's got

play01:13

to have a certificate installed

play01:16

but this API function essentially adds

play01:19

extra claims that it passes back to

play01:21

Azure b2c so it can be any custom data

play01:24

that your particular API wants to inject

play01:27

into the user's credentials essentially

play01:31

and they get injected into the token

play01:33

that then gets sent back to your front

play01:36

end

play01:37

but there's a problem because it's all

play01:40

great when it's up and running but how

play01:41

do we develop this locally

play01:43

so for the local situation we've got

play01:47

Azure b2c still

play01:49

and we've got our public endpoint so we

play01:52

can use our API that we publish up to

play01:55

Azure as part of our application

play01:57

and we can actually put a reverse proxy

play02:00

function into that API and that reverse

play02:04

proxy function can then pull our local

play02:07

development machine that we've exposed

play02:10

out onto the internet

play02:12

and that can do our custom claims at

play02:15

that point pass it back through the

play02:17

reverse proxy back to Azure b2c and into

play02:20

the ID token and the access token this

play02:23

means that we can develop locally and

play02:26

work out what our claims should be and

play02:28

get all that code working before we then

play02:30

publish that up to our public API so

play02:33

that what it looks like when we move to

play02:35

production is that we remove that

play02:37

reverse proxy function we reconfigure

play02:40

Azure b2c to directly call our function

play02:43

that just adds our claims that we've

play02:45

been developing locally but now it

play02:47

exists in our public API because we've

play02:49

pushed that up and so this is what our

play02:52

production architecture then looks like

play02:53

we could choose to remove that reverse

play02:56

proxy function at that point but

play02:57

obviously you may want to develop again

play02:59

locally to add enhancements to that

play03:02

particular function so it might be

play03:03

useful to to have that still inside your

play03:06

API your decision

play03:08

so let's go and dive in and see how we

play03:11

can set all of this up so the first

play03:13

thing that we're going to have to set up

play03:15

is being able to access our Azure

play03:18

function locally but from the internet

play03:21

so I'm on my router here and you can see

play03:26

that my

play03:27

local Azure functions run on an internal

play03:30

IP address on Port 7071 which is usually

play03:33

the default for Azure functions in a

play03:35

development environment

play03:36

and you can see that I'm port forwarding

play03:38

here from my external port on Port

play03:40

quadruple 8. so any request that comes

play03:43

into my internet IP address on Port

play03:45

quadrupilate will forward across to my

play03:48

Azure function API how you go about

play03:50

setting this up is going to be a unique

play03:52

situation for you there's all sorts of

play03:55

weird and wonderful ways that people set

play03:57

up their development environments these

play03:58

days so I'm going to have to leave this

play04:00

step to you but this is what works for

play04:01

me so with that exposed we can jump over

play04:04

into vs code and we can go to our API

play04:09

Now API functions where we have all of

play04:11

these and the first thing that we're

play04:13

going to do is set up this reverse proxy

play04:15

function that we're going to publish up

play04:16

to our publicly exposed API so let's

play04:20

create a new Azure function in here

play04:22

which is our simple reverse proxy called

play04:25

Simple reverse proxy it takes gets or

play04:29

posts and what we need to do in here is

play04:32

we're going to take the name of the

play04:34

function that we want it to proxy across

play04:36

to on the URL as a query argument

play04:39

so that's why we're using this query

play04:41

parameters dictionary here that I've got

play04:43

in a utility function here in this query

play04:47

parameters dictionary so this gets the

play04:49

query parameter and teases those out

play04:52

into a dictionary such that I can then

play04:55

query for a given value so I'm looking

play04:57

for a func query value on the URL so we

play05:00

need somewhere where we can store our

play05:02

response body as well then we'll have

play05:04

some error handling so if bunk to call

play05:09

doesn't actually

play05:10

exist on the URL then we'll just return

play05:13

an error a bad response or bad request

play05:16

rather and then what we're going to do

play05:18

is pull the configuration for where our

play05:23

actual API is that we want to proxy

play05:25

across to so in our case it's our our

play05:27

Local Host one but it's going to be our

play05:29

internet facing address

play05:31

on that Port quadruple 8 for me that I'm

play05:35

going to configure into this proxy API

play05:38

host environment variable

play05:40

so that's going to go into my local

play05:42

settings Json file here so let's just go

play05:46

and add that in while we're while we're

play05:49

here and for now just to prove that the

play05:51

simple reverse proxy Works locally it's

play05:53

going to proxy across to localhost 7071

play05:56

when we deploy to Azure we will set this

play05:58

up in the Azure portal and that will

play06:00

this will point to my public IP address

play06:03

and quadruple 8 as the port we can save

play06:06

that and close that and then let's carry

play06:09

on with this function so we've got our

play06:11

host environment variable but let's just

play06:13

do some check-in to make sure that we

play06:16

have configured that correctly and again

play06:18

if we haven't then we'll send back an

play06:21

error then we can start making our call

play06:24

to our API so we need a new HTTP client

play06:27

that's adding the right usings let's set

play06:31

the Base address for our request to our

play06:35

host and slash API which is where our

play06:38

API lives we can then create a message

play06:41

and we use the same

play06:43

method the same HTTP verb that's been

play06:46

sent in so if it's a post it will

play06:48

forward as a post if it's a get it

play06:49

before there's a get and we use our

play06:52

function to call that we got out of our

play06:54

query string up here as the function

play06:57

that we want to call so then if it's a

play07:00

post only because posts will contain a

play07:03

request body then we do that so we get

play07:05

the request body and we set that up as

play07:08

the content of the message that we're

play07:10

folding across we then make our call

play07:13

and we get the response back into

play07:16

an object here

play07:18

and then

play07:19

we can go ahead like we have done with

play07:22

all our other Azure functions and create

play07:24

a corresponding response from that and

play07:27

put in that response body

play07:29

so we send it back so that's essentially

play07:31

just called an Azure function by calling

play07:34

this Azure function so let's just run

play07:36

that up and prove that that works so we

play07:38

can see that we've got our new simple

play07:40

reverse proxy function available to us

play07:43

so I can come over to something like

play07:45

thunderclion and put in a get request

play07:47

give it a funk equals and the funk I

play07:51

want to call is version so I can see

play07:53

that I've got another API call called

play07:55

version down here and if I send that in

play07:58

I get back a 200 and the version

play08:00

information has been returned correctly

play08:02

so my reverse proxy is calling route

play08:05

background to my own Azure API and

play08:08

calling a separate function so that's

play08:10

all working so that's good so we can

play08:11

push this now up to Azure so that we get

play08:15

our reverse proxy functionality

play08:17

available in the cloud for us so I'm

play08:20

going to go and do that and then we'll

play08:22

come back and carry on while that's

play08:24

deploying we can jump over to the Azure

play08:27

portal and go to my static web app and

play08:31

the configuration settings

play08:34

and you need to add a new configuration

play08:36

setting here I've already done it so

play08:38

we're adding our proxy API host that we

play08:40

had in our local settings and as I said

play08:43

you want to configure this to your

play08:44

public IP address and whatever Port

play08:47

you're forwarding across to your

play08:49

particular API so that's all now

play08:51

deployed so I can go to my site that's

play08:55

up on Azure and go to the API call

play08:58

simple

play09:00

RP and give it the funk that I want to

play09:04

call and we'll call the version again

play09:06

and on my local environment I've got my

play09:10

Azure functions up and running and I've

play09:12

got a breakpoint in the version function

play09:15

so let's give that a go

play09:18

and I can see down here

play09:21

that Visual Studio is is flashing at me

play09:24

saying that it's hit a break point so

play09:26

let's go and we are inside of our

play09:28

function

play09:30

locally we've got our request coming in

play09:33

so I'm just gonna let that run

play09:36

jump back over here and I can see the

play09:39

response has come back correctly from my

play09:41

local Azure function so it's an internet

play09:43

facing reverse proxy that's calling my

play09:46

local development environment

play09:48

which is nice

play09:50

so that means I can now develop my API

play09:53

connector function locally and set up

play09:56

Azure b2c to call that reverse proxy but

play10:00

we're going to get to all of that in a

play10:02

bit so let's stop our API and let's go

play10:05

and start on our API connector function

play10:09

so we're going to have a function called

play10:10

user permissions which takes a post and

play10:14

I am going to cut some tutorial Corners

play10:17

here like most people do we should

play10:19

really have some authentication going on

play10:23

in this particular function so out of

play10:25

the box b2c for API connectors supports

play10:28

basic author or certificate auth so you

play10:32

should be validating that authentication

play10:35

I'm going to skip over that just the

play10:38

brevity of this tutorial because there's

play10:40

enough here to show you how this all

play10:42

works so given that you are

play10:44

authenticated from Azure b2c to actually

play10:48

call this API we can then get the

play10:51

request body

play10:53

as we normally do and we are going to

play10:56

create this request connector class so

play10:58

we're going to deserialize the request

play11:00

body into a request connector object but

play11:04

we'll create that in a minute we need to

play11:06

do some usual error checking so if our

play11:09

request connector isn't correctly

play11:11

deserialized then we have to return

play11:15

a set response

play11:17

from our API connector to inform Azure

play11:21

b2c to show a block page so it stops the

play11:24

authentication at this point because our

play11:26

API function has failed

play11:28

and we return that as a bad response so

play11:31

and if you want to see the information

play11:33

on where I got this from so it's from

play11:36

this page over here I'll put a link to

play11:39

this in the description but it's about

play11:42

adding an API connector to the sign up

play11:44

user flow white sign up I'm signing in

play11:47

and using it but anyway there we go and

play11:50

there's this example responses section

play11:52

down here so this is the example of a

play11:55

good continuation response so this is

play11:57

what you should return if you want the

play12:00

login to continue along with your custom

play12:03

attributes that you're adding in we'll

play12:05

get to that in a minute so this is an

play12:07

example of what I was just put in there

play12:08

for the error so we share a block page

play12:11

we put our error message in and version

play12:13

so if we jump back over that's exactly

play12:15

what mine looks like so that's our error

play12:18

handling so at this point you could

play12:21

perform any other validation that you

play12:23

want against the payload things like

play12:25

does the client ID match is the email

play12:27

present Etc you you can do anything

play12:29

inside your ISO function obviously so

play12:31

add as much validation here as you want

play12:33

to make sure that the consumer that's

play12:36

calling this function is who they say

play12:38

they are once you've passed all the

play12:40

authentication and validation checks you

play12:43

can then go and look up your custom

play12:45

claims that you want to add in so I'm

play12:48

hard coding this here but this might

play12:50

typically be a database connection

play12:52

lookup where you're going to find the

play12:55

person who's actually logging in so you

play12:58

get this claim coming in in the request

play13:00

connector as we'll see in a minute and

play13:02

at the moment I'm just checking if

play13:04

that's admin then I go and add the admin

play13:07

user role to the permissions so everyone

play13:10

gets to be a user but only the admin

play13:13

user gets to be admin is my simple case

play13:17

here that I'm putting in but obviously

play13:19

you can go and add in as many different

play13:20

types of user permissions as you want

play13:22

and I'm comma separating them here so

play13:26

they all go into the same custom

play13:28

property but comma delimited and then

play13:31

finally the last thing that we need to

play13:33

do inside this function is actually set

play13:36

up that response with our custom claim

play13:40

in it so we return a 200 response and we

play13:44

return our

play13:46

extra permission which is from our user

play13:48

permissions comma delimited string

play13:52

and we've called that user permissions

play13:54

it has to have the extension prefix on

play13:58

it that's a b2c convention so we have to

play14:01

adhere to that and that's all we need to

play14:03

do for our Azure function so let's go

play14:06

and create a new file in here request

play14:10

connector and let's just paste this in

play14:13

so that we can see what this does so

play14:15

here's our request connector class and

play14:18

so we can see that we've just got some

play14:20

properties in here basically and we are

play14:22

renaming these so that they get

play14:24

deserialized correctly so even though

play14:27

we've called it client ID the Json that

play14:29

will come in is client underscore ID so

play14:31

we've renamed some of these locally

play14:34

inside this object but essentially this

play14:36

is what gets passed in the step the

play14:38

client ID the UI locales the email

play14:42

address which is the all-important one

play14:44

because that's what we're using as our

play14:45

ID to look up our permissions the object

play14:48

ID which is the Azure object ID for this

play14:51

particular user and some useful other

play14:53

information like display name given name

play14:56

Etc so we can now jump over to Azure b2c

play14:59

in the Azure portal and we need to go to

play15:02

this API connectors option here

play15:05

and we add a new API connector we'll

play15:08

give it a useful name and we'll give it

play15:12

the name of our reverse proxy in here

play15:15

and we can copy that from here and paste

play15:17

that in there but we don't want the

play15:19

version function we want user

play15:21

permissions which is the Azure function

play15:23

that we just created and we'll send in

play15:25

some Basics so but we're not validating

play15:28

it but we should be yeah so usual secure

play15:32

credentials and we'll save that and then

play15:34

we've got to go to user attributes to

play15:36

add in our new

play15:38

custom attribute so these are all the

play15:41

default ones we're going to add in a new

play15:43

one I'm going to call it user

play15:45

permissions if you remember we had over

play15:47

in our Azure function we called it use

play15:49

permissions here

play15:51

so that that has to match

play15:53

and we'll make that a string give it

play15:56

some useful description and create that

play16:00

so now we have our user permissions down

play16:02

here which is a custom type

play16:05

and then we can go over to our

play16:08

user flow that we used for sign in so

play16:11

we've got our

play16:13

sign in flow and we can go to

play16:15

application claims and we can add in

play16:19

and select that custom claim that we

play16:21

just added and save that and then while

play16:24

we're in the sign in user flow we go to

play16:27

API connectors we can now see our user

play16:31

permissions function in here that's

play16:33

available to us so we can select that

play16:35

and that's how we wire up b2c to call

play16:38

that particular function

play16:40

when it's creating the claims so as part

play16:43

of the sign in process it will now call

play16:45

out to this API that we've configured so

play16:48

let's run all this up and give it a test

play16:51

and we'll put a breakpoint in our user

play16:53

permissions function just so that we can

play16:55

see that it gets hit okay so our app is

play16:58

up and running so we can this is our

play17:01

local one so I'm running on localhost

play17:04

I can sign in I get redirected to Azure

play17:07

let's log in as the admin

play17:11

in this particular case

play17:14

and let's sign in and again I can see

play17:17

I've hit a break point down in Visual

play17:20

Studio code so let's go and jump in

play17:23

there and here I am inside my user

play17:25

permissions so let's just step over some

play17:28

of this so we get our request body let's

play17:30

go and have a look at that so we can see

play17:32

exactly what that looks like and you can

play17:34

see that the email address is the admin

play17:36

has passed in so let's carry on so we

play17:40

add in our user permissions but

play17:43

essentially I've got a user an admin as

play17:46

the user permissions that I'm sending

play17:48

back so let's just run these through and

play17:51

we'll probably find that my

play17:52

authentication has failed because I've

play17:55

taken too long so let's just now that

play17:57

we've seen that up and running and

play17:59

working let's take that out

play18:01

take the break point out and let's try

play18:03

that again

play18:05

so that it runs through

play18:07

as we would expect and that has signed

play18:10

us in

play18:12

and I've got some debug Trace in here so

play18:15

we can go and look at the ID token

play18:17

claims and we can see there's my

play18:19

extension user permissions with user and

play18:22

admin being passed back in the token

play18:24

back to

play18:25

the next application which is exactly

play18:28

what we want the one on there

play18:30

let's just go and get the access token

play18:34

as well and if we come over to

play18:38

jwt.ms and paste that in we have a look

play18:42

at this here

play18:43

we can see that we also get the

play18:46

extension permissions passed into the

play18:48

access token so that means that it's

play18:51

available both to our client side next

play18:53

application but also to our Azure

play18:56

function API when we pass in the access

play18:58

token so that's really handy that it

play19:01

puts it into both tokens for us because

play19:03

we can use that on both sides to make

play19:05

sure that the user contains the right

play19:08

roles to be able to do what they're

play19:10

trying to do so that's all well and good

play19:12

but we're obviously not taking any

play19:14

advantage of that so how do we plug all

play19:16

this now that we're getting these extra

play19:18

user roles back into our next

play19:21

application so let's get rid of the dev

play19:24

tools let's come back over here and we

play19:27

know our function API is now working so

play19:29

we can now

play19:31

close up the API side of this and start

play19:33

looking at the next side of it and how

play19:36

we can take advantage of some of this so

play19:38

inside of our user store we've got our

play19:40

auth user store

play19:42

what we're going to do is add in a new

play19:45

getter in here and we're going to ask if

play19:49

the user has a particular permission so

play19:52

it's going to query the token that it's

play19:54

storing inside this store so we have to

play19:56

pass in the required permission that we

play19:59

want it to test for and that's going to

play20:02

give us back a true or false result so

play20:06

inside here we can have an if test that

play20:09

says if we've got a current user and the

play20:12

user

play20:13

has the user permissions claim so what

play20:16

we're going to do is we're going to look

play20:17

in the user permissions string and we're

play20:21

going to see if it contains the required

play20:23

permission string that's been passed in

play20:26

and if it does we return true so the

play20:28

user has that permission and if it

play20:30

doesn't we return false and if we don't

play20:33

have a user or the user doesn't have any

play20:36

user permissions claim in it then we are

play20:39

just going to return false back out of

play20:42

this method

play20:43

so let's save that so then inside of

play20:47

something like our header component and

play20:50

we can now rather than always showing

play20:53

this admin link let's change this so

play20:55

that we only show the admin link if you

play20:57

are in fact and a user that's got the

play21:00

admin role so we need to import the auth

play21:03

store in our script as we normally do

play21:07

and then we can use the auth store to

play21:10

get out the user has permission getter

play21:13

and once we've done that that's then

play21:15

available to us inside of our next

play21:17

template up here

play21:19

so we can put in a the if user has

play21:24

permission and pass it the string of the

play21:26

role that we want the user to possess in

play21:28

order to show this particular next link

play21:31

so let's save that so that's our app up

play21:34

and running and as we can see we don't

play21:36

see the admin menu here so let's go and

play21:40

sign in let's

play21:42

start by signing in as someone who's not

play21:46

the admin so good old data just a

play21:49

general user he can log in and welcome

play21:52

Arthur Dent but he doesn't see the admin

play21:54

menu but he does see restricted areas

play21:57

because he is logged in and let's sign

play21:59

him out let's sign back in as the admin

play22:03

this time

play22:06

the admin gets the admin user role and

play22:09

so we see our admin link over here so

play22:12

that's UI stuff inside of nux that you

play22:15

can take advantage of the UI rolls quite

play22:18

easily but what about our apis if we

play22:21

want to restrict things in our API so

play22:25

let's jump back over here

play22:29

and we can get rid of these

play22:31

so inside of our API we've got our

play22:34

isolated function authorization

play22:38

so we're gonna go and make some changes

play22:40

to this to take account of the user role

play22:43

that gets passed in

play22:44

so let's jump into the authorization

play22:47

middleware and right at the top where

play22:50

we've got our Scopes we're also going to

play22:52

add in our rolls claim type which is

play22:55

extension user permissions as we know we

play22:57

saw that in the access token

play22:59

and then we can change the authorize

play23:02

delegated permissions here so last time

play23:05

I commented out about user roles and

play23:08

said I'm not interested in those but I'm

play23:10

now going to change this so that it does

play23:11

take account of user roles but it looks

play23:13

at my b2c extension

play23:16

I'm going to look up the claim for the

play23:19

user permissions and split that by the

play23:23

delimiter so comma and a space and I'm

play23:27

going to remove any empty entries so

play23:29

this will get me a collection of the

play23:30

user roles now I've got a collection

play23:33

that I can use

play23:35

I can query that collection to see if

play23:38

the role that's been specified against

play23:41

the Azure function exists for this user

play23:44

so this user possesses the right role to

play23:46

be able to call the Azure function that

play23:48

they're calling and we'll go and change

play23:50

the attribute that we put on the Azure

play23:53

function to State what role they need to

play23:56

possess in order to call it so that's

play23:58

what this is doing here we just need to

play23:59

change the last line as well so that as

play24:03

well as checking the accepted scope so

play24:06

exactly what we what it was doing

play24:08

historically which is to check that the

play24:10

user has the role and the scope we

play24:13

changed this last time so I'm going to

play24:15

put it back to how it was so now they

play24:17

have to have the role and the scope in

play24:20

order to call the function so let's save

play24:22

that and then let's jump over to our

play24:27

API

play24:28

and we've got our b2c

play24:32

protected function in here that at the

play24:35

moment you have to have the email scope

play24:38

in order to be able to call this so we

play24:41

are going to change this so that as well

play24:43

as email access we give it a user role

play24:48

of some value

play24:51

and let's say

play24:53

admin so only admins can now call this

play24:57

b2c protected function let's save that

play25:00

and start this up okay so that's up and

play25:03

running so let's jump over here

play25:06

and we're not signed in so let's go and

play25:08

sign in

play25:10

and let's do the same test that we did

play25:12

before so let's sign in as someone who

play25:15

isn't admin I'm going to put on the

play25:18

developer tools

play25:24

so we can see there that my b2c

play25:26

protected function gave me back a 403

play25:29

Forbidden because he's not an admin role

play25:34

so then let's sign out and sign in as

play25:37

admin

play25:42

thank you

play25:43

this time we get a 200 for our b2c

play25:46

protected function and we see our data

play25:47

on the page so

play25:49

that shows how you can protect your

play25:52

Azure functions as well and make sure

play25:53

that the people that are calling them

play25:55

have the right roles in order to be able

play25:57

to call them so that's front end and

play25:58

back end secured with user roles using

play26:03

Azure b2c so if you found this useful

play26:05

please do hit the like button that helps

play26:08

it find more people and with that I want

play26:10

to thank you very much for watching and

play26:12

I will see you in the next video

Rate This

5.0 / 5 (0 votes)

Related Tags
Azure B2CAPI连接器用户角色权限管理开发本地化反向代理安全认证自定义声明前端集成后端保护角色基访问
Do you need a summary in English?