well good morning everyone
thanks for coming my name is Jimmy
Bogard you can find me on Twitter at J
Bogard all the code you see today as
well the slides you can find on my
GitHub at github.com
and I blog about this topic and a lot of
the things on my blog at
jimmyboguard.com
this is actually a topic I wish I didn't
have to talk about I wish I didn't have
to worry about security and things were
just like easy to connect up on the web
and people can try to hack it and things
like that but that's not the case
um I do have to worry about security and
so this uh this talk is about a project
I recently worked on in which I had to
take basically a crash course and all
things security and understanding how to
deploy secure microservices into azure
so things used to be quite a bit simpler
we used to just have like a very basic
client server application so we would
build server-side web applications I
remember those things like the HTML was
built on the server as opposed to the
clients excuse me and then there was a
talk to a database and we would secure
the communication from the server to the
database so nothing you could talk
straight to the database directly of
course we would have it behind a
firewall something and then we just had
a client and things were simple in order
to secure these things we would use a
cookie to be able to secure this we'd
have a like asp.net core or asp.net
secure cookie that was encrypted and
only the server could read it it was
stored securely in the client as well
and no one else could communicate to our
server unless they had that cookie and
they were authenticated
um so that was pretty simple right like
that's that's that's the days I wish I
could go back to but unfortunately
things are not simpler anymore
um we added microservice to the
microservices to the mixed
um which means a much a lot more servers
a lot more things talking to each other
and so the the store becomes quite a bit
more complex when we're talking about
adding a lot of other different
distributed components to the mix
so this is my situation that I was
presented with which was I had a client
that was of course a spa because you
have to these days right so it's an
angular Spa that was talking to a single
API that was the back end for front end
so the back end for front end
represented how to pull all the
different Services behind the scenes uh
formulate responses uh for whatever the
spa needed and then the spa would just
talk that one single API
and then behind the scenes the BFF would
then talk to all the different back and
microservices that had their own
databases their own applications they're
all running on like kubernetes or some
junk and be able to pull that data back
together for that response I was showing
on the screen
we also had a lot of on-prem servers as
well so we had like still existing
Legacy applications Legacy systems they
were on premise also talking to these
apis and also need to pull back data to
be able to be shown on their different
screens
so this is the question we Repose is
okay
um the previous picture where we just
had like a single client server we
understood that picture very well like
how to secure that like you log in you
get a cookie everything's good but how
do you secure this picture by the way
I'm not talking about network security I
have no idea about any of that stuff so
if you're looking about network security
like this is not the talk for you
because I'm not the person to be talking
to about that we remain looking at the
the like apis themselves how do you
secure these different apis together
so that uh the the data that was being
shown in each of these different systems
uh was the data shown to the right
person
um it was also Health Data and personal
information so we want to make sure that
you know the wrong person couldn't sing
the wrong person's data
and so how that was our big question was
how do we authenticate and authorize
these different external users to our
system
now for the external users the people
they were like you know the actual users
of the system they never talked directly
to any of our individual microservices
in fact no no no external user
whatsoever internal like internal users
or external users talk directly to these
Services they're always going through
something else some other API or some
other system that then talk to our back
backend microservices
so the front end we saw that okay uh the
front end users who have a regular kind
of login that was actually somewhat
straightforward because we were using
auth0 at the time to authenticate those
initial users so
um they would go to some kind of single
sign-in page that entered the
credentials and then when they they
would get logged in and get a secure
cookie do the back and for front end
as well as the token however
all the other background systems and
services didn't understand r0 and
complicating the matters was all these
things in the right
over there all those on-prem systems
also don't use r0 they were just still
using like forms authentication login
cookies things like that so we couldn't
just say let's just take that token that
we got from osiro and flow it through
all their services because those things
on the right don't have any concept of
osiro and didn't have any sort of token
so we're leaving this world that was
very very mixed excuse me authentication
environment where we had like modern
sort of logins over here and then like
old uh kind of crusty logins over here
on the right and the things in the
middle I had to be able to speak both
languages
so
our unanswered questions was we can
understand how to like to secure the
things that were on the outside of the
of that diagram we understood how to
secure the BFF I could just use cookies
we understand that we could share the
existing applications they could just
keep doing what they're what they're
already doing
but all those things in the middle all
those micro services that were that how
the uh how that critical business data
the critical user information
how could we secure those different
pieces from both directions
in a way that was consistent and still
maintainable
um so
years ago someone else I knew not myself
definitely not
um we'll just say well you know what
we're already inside the network right
we're already past the firewall why do
we need security at all why do we even
need like https Transport Security just
build these internal apis and assume
that if they were able to get into the
first server then they should be okay
with everything beyond that so just
don't do any security at all
it wasn't me someone else I I don't know
I'm sure
um
and so we also had to worry about all
the on-prem people as well that we had
to worry about okay the the internal
Azure communication as well as the
on-prem communication
so uh people the smarter than myself
looked at this picture and said right
this could be a security disaster if we
just do nothing here if we just let
anyone communicate to these apis it has
this protected health information that
has uh personal identical information uh
we can't just allow anyone if they just
happen to be on the network to be able
to call these apis and get whatever
information they want
so instead we were trying to shoot for
what I learned later What's called the
zero trust model and the idea here is
that we never trust any bit of
communication and we always verify so
you always verify any sort of
communication between one system and the
other and never just say like well if
you made it this far I'm sure you're
good
so our first thought was well why don't
we just flow that user token so take
that same at that same authoro actually
at the time we were using identity
server transitioning to auth0 and say
let's just take that jot and just flow
it through all the communications
Downstream say well just we'll just keep
passing that that connection along
that would work great except
two problems one none of the things on
the right hide any concept of a user
token to begin with they had a cookie
and the other thing we were running into
was that not every single kind of call
in our system was made by a user
sometimes we had things like batch jobs
or messaging that would not have a user
whatsoever or they were making calls to
our API so we don't have any concept or
context to say who that specific user
was to kicked this thing off they didn't
exist
so this looked great in concept but
broke down pretty quickly we looked at
the different kind of scenarios
so our solution solution was right we
can't use
the identity provider on the right as
just a thing we're going to use
everywhere and the things over here have
no concept of this thing on the right
the austerial components then we need to
find some homogeneous solution for all
these different Connections In The
Middle
and because we were hosted on azure
we said right why don't we use Azure ad
to secure all the communications inside
of this picture
so every single Arrow here once I got
inside of azure as well as the on-prem
network all those would use Azure ad
Azure active directory I think it's
called Microsoft identity they've
rebranded yet again in any case we would
use that as the thing that would be able
to secure a token and secure like who
you are and what you're looking for
inside of all these different
Communications
picture that we were given to by the
security folks like yes do this I say
great how do we do that I said that's
not our problem I said oh
now I have to figure this out so we had
to figure out okay
um for each of these different arrows
here how should those different systems
authenticate with Azure active directory
so Azure active directory supports a
number of different by basically all the
different oauth 2.0 flows and again with
this one of the things I wish I didn't
have to worry about I wish we could just
use cookies and everything's wonderful
but no this is more complicated with
microservices all these different
systems so we had to figure out okay how
should each of these systems when I want
to call from system a to system B how
should those systems authenticate and
acquire that token
and there are a lot of different options
available to us in oil 2.0
um we uh this is from the Microsoft
documentation about here's all the
different kinds of apps that you could
build and they're different these are
the different ways you can or you should
acquire token for each of those
different situations
so if you have a spa you should use auth
code with pkce for whatever pkce means
and then the kinds of things you can
authenticate against like who who can
actually authenticate are the fun things
of azure ID which are work or school
accounts personal accounts or Azure b2c
which no one should ever use
and so looking at all these like okay we
started going on the list okay that that
doesn't look like us that doesn't look
like us that doesn't look like us then
wait a second we have a web API because
it calls other web apis that's our
backend for front end it's an API that
calls other apis
we also have Daemon apps or you know
these background services that also call
apis and so they told us that you can uh
now you're down to these two options for
uh oauth 2.0 one is the on behalf of
flow which is basically
I get a token and then my service needs
to call another thing so it acquires a
token on behalf of that token so I don't
flow the same token down instead I
acquire a new token on behalf of that
calling user and that new token will
then also include the information or the
claims from the initial user that seems
pretty good except the kinds of accounts
I can use here are only work or school
accounts whatever that means or personal
account so that means that I can only
use tokens that originate from Azure ID
to use that flow that's the limitation
of azure ID so we saw that like that
would have been nice it would have been
nice to say okay you're this specific
user
um so only show the date or hide the
data based on that so we said okay
we can't do the on behalf of flow
because you're not an Azure ID user to
begin with we have on-prem systems that
have no tokens and the client systems
that are just using um
Osteo and identity server so that one's
out so they basically just reduced us
down to this one which is demon apps the
call Web apis so everything that was
going to call our different Services
would need to use client credentials
which is every single client gets a
client ID and a client Secrets which you
have to keep secure and then using that
client ID and client Secrets they call
Azure ID to get a token and after they
get a token they can then call our API
passing in that token through the
authorization header and then everything
should work okay
long Journeys to just like choose that
one different option there
now that's just how to authenticate
which is to establish the identity of
the caller the second part then is how
to authorize those callers
so in Azure ID once I go the route of
client credentials that is machine to
machine communication you have two
options to authorize individual callers
the first option is known as Access
Control lists or ACLS which is just a
fancy name for just do whatever you want
inside of your application it's all
custom logic you just like take the
token look who's calling you and say
right are you authorized to be able to
call this API endpoints or are you not
authorized to call this API endpoint but
it's all just custom logic inside of
your application there's nothing fancy
or special I'll look at who the client
ID is that's calling me and do I trust
them or not and if I don't trust them
for the specific call they say
you can call me
but that requires us to have each
application maintain its own Access
Control list it has to have that list of
who are the authorized callers for this
API or I could just say you know don't
do that just say as long as you have a
valid token you can call us which again
we were trying to avoid because we're
trying to go to the zero trust model
on the other option though is known as
application permissions and the idea
here is that I Define custom roles that
are modeled as permissions inside of
azure ad
and then I can assign those different
custom roles or permissions to
individual server principles
and then when I acquire a token as
client a calling to server B I ask Azure
ID I want a token for that resource and
then Azure ID looks up do you have any
roles or permissions assigned for that
resource resource and then the token
that you get back will contain all those
roles or permissions for that one
specific resource
and then the server once it receives
that token well then say for this API
call are you authorized for this
individual role of permission so I don't
care who you are I just care do you have
this specific role of permission
so we like that one because our
individual applications then don't have
to maintain that custom list of who is
calling me and what do they have instead
of just say do you have this permission
and that's it and that assignment of the
permission is then done outside of our
application outside of our system
so from this we we boil it down said
based on this complex scenario of
microservices on-prem all that sort of
stuff we're able to build a very
simplified application or simplified
system that represented the kind of two
main use cases in application we have
internal Azure communication so that's
like something deployed to Azure calling
out something else deployed inside of
azure and then we also have these
external clients that are calling into
our system as well these external
clients are not deployed to Azure and
are demo it'll just be deployed to my
old laptop here but the idea is that
it's not inside of the Azure ecosystem
so our choices become a little bit more
limited into how we secure that
individual communication
at no point though do we have any kind
of external client talking or external
user application talking directly to our
apis so the browser does not talk
directly to our application it has to go
through this other API that then calls
our API
so I don't have to worry about all those
different other user flows and we can
make sure that these back-end servers
that are not actually you know exposed
to the public internet all those sort of
things
all right excuse me
so I've got these basic scenarios laid
out I have internal Azure communication
I have external Azure communication to
our system
the next piece we need to unders decide
is okay we want to use this like
role-based authorization
what are the roles
so we had to figure out you know what is
the what kind of makes sense for all of
our apis to Define these individual
roles for our different apis
so in this application I'll be showing
you it's trying to have something a
little more complex so it's not just a
street like read-only API it's a to-do
API that has all sorts of different API
endpoints to be able to modify add new
to do items and delete them as well
so we've got our normal kind of crud
oriented API here we have git put post
and delete
so looking at this we need to Define
individual roles for each of these
different kind of API endpoints
so we had to go back and look at what
are the kind of use cases we're looking
at to be able to uh you know kind of
decide what sort of granularity we could
put on these different roles
so I could be extremely again granular
like so every API endpoint has its own
distinct individual application
permission so like to do dot read to do
update to do.create to dot delete
but then we looked at our applications
we saw that well there's not really that
sort of breakdown like this application
can create something but that
application can only update something
there was never that sort of breakdown
and so what we had was there are certain
systems that could read the data and
there are certain systems they can read
and write the data so we wind up mapping
those roles and permissions out see
something a bit more simplified that was
uh just read and write
now again you don't have to go this
route of creating application
permissions
you could just use the access control
list and say you know if you've got a
token and you're my list of uh you know
qualified people they can call me then
you're good to go
um well we found this though because we
were dealing with protected health
information and protected user data
governed by you know laws and
regulations and such we only wanted
specific applications to call us that we
knew that they can then apply those
appropriates like data protection
privacy uh attributes to that data
before it actually went out the door to
the end user so we wound up going the
application permission route to ensure
that only the specific applications that
can read this protected data because not
all of it was protected that were then
those applications they could call us
but other applications that could didn't
have that sort of capabilities to be
able to protect that data said well you
can only get access to the apis that
don't have that information inside of it
so we went up the application permission
route and tried to just focus the
granularity of these permissions based
on the overall business use cases there
are not like there's not like a lot of
documentation or guidance from Microsoft
or any of their identity writer out
there really about what these
application permissions coders should be
so we kind of had a you know figure it
out based on our individual use case
so with that let's go to our demo and
our demo is going to be exactly this in
which we have a server deployed into
Azure we have an Azure client which is
another API deployed into Azure and then
we have an external client which is just
represented as a worker application
calling our API from my laptop
all right
so I've got uh Visual Studio here I've
got
in our application here in our solution
I've got my Azure server so this is an
API that will be then deployed out to
Azure as an app service I have an Azure
client which is another web API that
calls our API uh also deployed out into
Azure and then finally have the external
client and that piece is the um the
application they'll be just running on
my laptop
so first things first we need to build
out the Azure ad resources in order to
secure our server so we'll go to the
server first then we'll look at the
external client and then we'll look at
the Azure clients
now to build these resources out I could
go to the Azure portal and kind of Click
around there to create all these
different resources but that's no fun I
also wanted to use uh infrastructure as
code because that makes it a little bit
easier for us to understand the actual
resources being created for us behind
the scenes
so I'm using palumi this is not a plumy
talk I'm just using palumi because
c-sharp and so we'll be using palumi to
create all the different Azure resources
for our servers and our clients
all right so let's first go to our
server resource
it's empty now but we'll soon have stuff
inside of it so the first thing we need
inside of this uh to create our server
is going to be the actual app service
so I'll go ahead and
create that first
so this uh this app service is an Azure
uh app service and so it's just a web
application that calls our Azure server
application such as.net Azure server and
so this is going to be the actual
deployed application inside of azure
but it has no security associated with
it by itself if we want to add security
to it we have to add additional
resources to it so the next thing we're
going to add
is our server application
okay
So This Server application
is a secured resource inside of azure so
when you want to secure any kind of API
or yeah I guess mainly apis then you
have to have some kind of container for
all those different security rules and
that's going to be this application here
I will go over to
the Azure portal just to show what this
looks like
so let me go to it's called app
registrations
and this is our Azure ad example server
so when I run this palumi uh up command
it will create this uh this application
here
now every single kind of identity
provider oauth 2.0 like a token provider
has different concepts for how you
secure these kind of Standalone
applications so austero has its model of
how to secure applications
OCTA has its model Azure ID has its
model identity server has its model but
the general idea is that if I don't have
a user that's calling different apis
that have another application calling it
other apis then it's going to need to
use the client credentials flow to
acquire token and they need some way to
identify who the clients are and who the
servers are
so an application or app registration
inside of azure represents that identity
of some application that's calling
another application so represents both
the client and the server
all right so this is our server
application not a lot going on here to
say here's my uh here's the here's the
name of the application so that Azure ID
example server is what I see right here
and then I have a specific URI to
identify it so instead of going based
off like a good when I wanted to get a
token for something I will use this URI
itself and that shows up right here API
slash example server
ah there we go
okay so that by itself uh is just a
container for what is going to be our
security rules
the next thing I need to Define though
is our roles or permissions for this API
so the roles are going to live inside of
azure ad and then my application is
they're going to authorize those rules
but Azure does need to understand what
are the different permissions and roles
from application so that when I acquire
a token for a resource it can say do you
have this permission
so
I will now create
our roles
there we are
all right so I'm defining two
application roles here one is to do dot
read and one is to do dot rights
and over here these two components here
are just IDs of these roles because when
I want to assign a role to another
resource I need to know which role I'm
assigning and so those IDs are the
things I'll be using to say assign this
role with this ID to this client for
this server
all right so at this point
my server has its roles defined as part
of it and I go to the portal if I go to
app roles
I will see now to do.write and to do
that read by the way I'm not actually
running plume up all the time because I
don't trust the like Azure to be able to
do the things in real time while we're
doing this demo um so I've already run
all these different polymer commands I'm
just gonna be adding them one by one and
explaining as we go
a little bit of a cheats but that's okay
all right so I've defined these two
different application roles uh to do
right and to do.read
how do I sign up roles yes let's look at
that next but first we've we've created
these roles we need to have our server
actually enforce this authentication
authorization uh these authentication
rules
so now
um I will go back to my server
application
and add the code necessary for it to
authenticate via Azure ID
and authorize against those specific app
roles
okay so this is just a normal kind of
vanilla web API I've got uh you know API
controllers here that has the to do
items uh this one you know does all the
get put post delete and then I also have
another API just to show like what it
would look like to not secure an API so
I have an API
uh that doesn't um this endpoint is just
I guess weather so it's not that
interesting um so this one will not have
security associated with it the to do
one will
okay
so first
we'll pull this over
and we need to tell our server to
authenticate using Azure ad and to do so
we'll be using
the Microsoft identity web package so
this package integrates directly with
asp.net core to give you all that
middleware authentication authorization
against Azure ID underneath the covers
it's not doing anything I guess it is
doing something interesting
it is going to look at the incoming
requests look at the authorization
header grab that Bearer token that jots
look at the issuer and say are you a
valid jot for this you know for Azure ID
and are you calling my API that I am
identified with this specific ID
and so to get all that we just say add
Microsoft identity web authentication
let me bump this font up just a little
bit
oh that was a lot
all right
um so we say add Microsoft identity web
API authentication and then we'll pass
in our configuration to say these are
the different configuration values for
who are you what's what is your you know
what issuers should you validate against
that sort of thing
so to determine like what
I should be authening authenticating
against
yes we'll go to this one we need our
configuration so what is this
configuration that we need I'll just
pulled over first
we need
to understand what is our authentication
server
so what is the instance of azure ID that
we're authenticating authenticating
against this is just like the normal
Azure ad login but if I had a custom URL
or custom kind of Landing point for
Azure ID that would be that different
URL there
I need to know the Azure ad tenant so
this is the same for all of my Azure ad
um resources so all the users all the
groups everything is going to be
umbrella into that single tenant and
then the next thing I need to know is
who are you like who is this server and
so I have to give it the client ID this
is a little confusing because I have
clients and I have servers and they both
are called applications and they all
both have client IDs so this client ID
represents the client ID of the server
even though it's called client ID
where do I get this
I get it
from here I have a application client ID
I have the directory and tenant ID and
those two pieces I'll drop in
right here actually I can get it from
palumi so I'm using plume to spit out
the different configuration values so my
server application client ID is this as
well as the host name and other things
we'll be creating here in a little bit
all right so I've got all my
configuration here
this configuration then feeds directly
into
this call here and so the server will
then look at the token and say was it
issued by this Authority this issuer so
log in microsoft.com and is the audience
uh this specific ID and is the uh other
thing the server I'm wanting to talk to
is that also in that token as well so it
looks at all the configuring and you
know matches it up and says right do all
these match these different values exist
in that token then you're good to go
all right now
in my API I have to authorize those
individual roles so I will say over here
this is the get action so that will be
to do dot read
this is another get action so that will
also be to do.read
this is a put action so that would be to
do.write
and then this action will also be a post
so that's going to be to do it right and
then delete
to do that right as well
so this is kind of funny I have
authorized I'm authorizing specific
roles with this role that is our
excuse me there's our permission so we
have a permission called to dot right
and to dot read and behind the scenes
this authorized attribute will look at
our identity the principle and say do
you have this role but where those roles
come from how did asp.net core know how
to take that token and then populate
those roles and my identity
and my principal inside of this so right
here this is just a normal authorized
attribute I'm not telling it to use
Azure ID anything like that so something
is translating from the roles coming in
on the token to the roles being assigned
to my individual identity and principle
so that's the last piece of this
configuration here I tell it that the
roll claim type
is called roles so on my token we will
have a claim called roles that include
that is the list of all the different
permissions that have been assigned to
this resource and then Azure the
Microsoft identity web middleware will
take that incoming claim take those
roles and then apply those roles to our
identity underneath the covers so then
in our controller all we got to do is
then authorize this specific role
now if I were to run this application
actually just let's just run it
when I want to test this locally I'm
going to have a problem
because
if I try to call any of these apis let's
yeah let's try it out when I execute
this API locally
oh unauthorized because we're not
supplying a token to this server and so
locally it's like well I'm you know I
still need a token for you to call me
and you don't have one
so our next problem was
how do we achieve local development with
this API that's only supposed to be
called by other apis I still need to be
able to get a token as me a developer
calling this API locally
I could turn off security locally but
that's no fun right we still want to
test out these different flows and these
different middleware so I still want to
be able to call this API and get a token
so how do I as a user acquire a token
for this API
well we had to go back to that list of
different oauth2 protocols and say what
makes sense as a user calling this web
application to call this API
naive me said let's just use the same
protocols we were trying to use for
everything else let's use client
credentials so I have a client ID and a
client secrets and I'll Supply that
client ID and Secret inside that Swagger
UI and then I'll acquire token to get
that information that get that to get
that token
not so fast Azure says I will not issue
you a token if you originate from a
browser using client credentials why not
because you should never use client
credentials inside a browser or desktop
or you know client application because
we should we don't have the ability to
store that client secret securely so
Azure ID says no thank you you can't do
that
um and so if we tried to use client ID
and client secret the client credentials
flow via Swagger Azure ID would reject
that and say I don't support that flow
from this specific resource which is a
browser
okay
um so what can we do instead well um
we'll just use one of those other
application flows and so when we looked
at you know a browser server calling an
application it told us to use the
authorization code flow and so I do have
a user and Azure ID like me my my actual
account so what if my user gets access
to the API and then me as the user
developing locally I acquire token on
behalf of myself using off code and then
I get that token from Azure ID that
represents me calling the API versus
some other server
um but to do so we need to authorize my
user to have those specific application
permissions I can acquire token via
Azure ID but if I want to acquire token
for that specific resource for This
Server then I need to be assigned this
permission so that I get those roles in
my jots
so let's do that
to do so I'm going to need some more
Azure ad resources let's go back over
here to Azure ID
and then over in our server
actually this is going to be in yep
that's right
um in order to acquire token as me the
individual user uh I need to apply a
couple other things on top of azure ID
so the first thing I need to do is
Define a scope for which my user will
ask for permissions this is just a
made-up scope so it's just a limitation
of azure ID unfortunately that says if
you're an end user asking for a token
via auth code flow then you do you need
to authorize against a scope and so I
don't care what scope it is just make
something up and so I said right this
scope which is called local Dev and then
when I ask for the local Dev scope I'll
also get my other claims which are going
to be the roles
the next thing I need to do is modify my
application definition in Azure to
accept this new kind of authorization
code flow let me go ahead and add that
next
so I say I'm going to expose an API that
has this oauth 2 permission scope called
local Dev so there's the local Dev scope
uh with this with this ID
and then I'll also include a redirect
URI that I will I say this is okay for
us to do this specific flow so this
redirect URI is going to be my Swagger
redirect so when I try to acquire token
from my local browser running on my
desktop then it will say oh yes this is
an okay redirect to be able to get your
your token
all right now the next thing we're going
to need is going to be our
assignments of those roles to my user
so I'm going to go ahead and pull it
over
here
so we have a few resources here one is
going to be the Principal
that's going to be the target of
assignment of our roles so that's This
Server service principle the application
itself I can't secure directly so the
way Azure ID works is everything is done
via principles and then this application
will then now have a principle attached
to it so the roles I'm assigning are not
to the application but instead of this
other securable resource there's like a
database diagram calling out somewhere
that's like there's a principal table
and I've got like application table that
links to that principal table and I got
users that are also principals and
groups that are also principles and
those are the things I assign roles to
not these like applications themselves
uh the next thing I need to do is uh say
that it's okay for visual studio that's
running locally to be able to make
authorization requests so this one is
saying
um I will say it's okay for visual
studio to ask for a token from API and
this is a quote quote well-known client
ID that you have to Google for and
what's one of the things that you Google
for it and there's like a bazillion
results on on stack Overflow like what
is this ridiculous good that I have to
stick in here to be able to call my API
well this is it when Visual Studio makes
a call out to get our API the
application ID it uses is this one it
hasn't changed in like 12 years so it's
okay to hard code it
if they change that so many things break
so that's just what it is
um there are other sources I can use to
be able to call that so if I'm using the
Azure CLI or Visual Studio code those
also have their own client ID so just
Google you know Visual Studio code
client ID and you'll find that other you
know quote quote well-known good
all right
lastly I need to assign
my user those individual roles
and so I'll do that right here
I will have two methods here one is to
assign the read and one is to assign the
right and so to assign the read
permission I have to say you know who is
the principal that I'm assigning to what
is the role I'm assigning and what is
the then client ID of the principal that
I'm assigning that role for so I need to
know like the client the server and the
role and so that's all here I have an
app role assignment that includes the
app role ID the ID of the role of My
Signing I have the principal and which
I'm assigning for and then I finally
have the resource in which is going to
receive the or yes the principle I'm
assigning for the client and the
resource of the server which is the
server service principle object ID
again this is basically a database table
somewhere that is a role ID client ID
server ID and that's what this command
represents is creating that record that
assigns this role for this client to
that server so I have one for read and
one for write
and finally I'm going to assign the
roles for
my user
so this will assign read and assign
rights for my not user what it decided
to do for our Dev team was instead of
assigning each individual user all these
different permissions I can also just
assign all those users to a group an
Azure ad group and then assign the group
those permissions so instead of me
having to like revoke individual users I
just say if you're doing local
development
get added to this group and you're good
to go
so over here
I need to actually assign those roles so
right here enter
main set of infrastructure as code bits
that are creating the server or clients
and our external clients I will go ahead
and then assign those roles
so I say server dot assign roles it's
going to assign those those roles based
on my Azure ID resources and this is
then just my user and the local Dev
group that I've created earlier
okay so now with all this
I need to enable
security through Swagger in my server so
I have to teach Swagger how to
authenticate with Azure ID so that's the
next bit we're going to add here
so
down here we have our add you know
app.use Swagger and over here we have
ADD Swagger so in our Swagger
configuration we'll need to say go ahead
and
authenticate via Azure ID with a
specific flow
so I have to tell it you're going to use
the authorization code flow which is the
normal flow for a browser and these are
all the URLs you need to go to for the
authorization URL for the token URL and
the scope is going to be
that local Dev scope that we asked for
earlier
finally down in the UI we have to do a
similar kind of operation
then we say the client ID that I'm going
to be passing in through the UI is this
and other junk use pkc PC kit whatever
all right so now when we run this
we'll get this little padlock in our
Swagger UI when I make that call
aha authorize
authorize against this scope what is
this client ID well
that is the client ID of Visual Studio
the well-known client ID the F12 if you
Google that like you'll get like lots of
results back I click authorize
whoa just like really quick so I was
already logged in to Microsoft online
Azure ID and so it said right oh you got
it's you're already authenticated let's
go and grab a token and so now at this
point it has a token it can use for any
of these calls
so now when I test these apis out
executes
and I grab
I'll get we got 200 so we got a good
response and we got you know actual
responses back
and if I grab this bear token right here
and I go to jot.ms
let's look and see what this token looks
like
and so down here
I've got me
James Bogard I've got my scope of local
development and hey look there are those
roles that I assigned to my group
and the group I'm a part of that group
that group has been assigned those
permissions and so now those roles get
populated in the jots when I call the
server it takes those roles puts them in
the the roles in my principal and then
in the authorized attribute it just
looks at those roles to say do you have
to do that right and to do that read so
now I can develop locally huzzah
all right we're not done yet though
that's just the server we still have to
worry about the external clients and the
Azure client so let's do the external
Client First
okay so the external clients
so what does the external client need
this is something that's not deployed
into Azure but still has to identify as
an Azure ad resource so that I can get
permissions assigned to it and it can
acquire a token
so
we first create our application this is
kind of funny because it's not something
that actually gets deployed in Azure but
in order for us to assign permissions to
something I need to have some kind of
securable resource so I'm able to just
create an application that never
actually gets deployed but is something
that just exists inside of azure ID
and again all identity providers have
some sort of concept of this thing Osteo
has applications as well and you know
role-based Access Control it's a very
similar concept across these different
identity providers
uh the next thing I need is a secret now
there's a few different ways for us to
acquire a token via Azure ID as a demon
application you have the uh the client
ID client secret option so that works
great if you can secure that secrets you
can also use a certificate that's my
preferred option is to use a certificate
because those certificates I can then
store securely inside of key Vault and
have permissions associated with those
or you can use a Federated token the
Federated token is I'm acquiring another
token on behalf of another token I
already have we don't have that so we
just wind up going with the client ID
client Seeker out because it also is
easier to build locally here
okay so I've got my application Secrets
I've got a service principle and so that
service principle for the external
client is going to be the thing in which
we assign these different roles to
my external clients then needs to
acquire tokens on behalf of this Azure
ID resource so we're going to need some
configuration there first
over here
we're going to pull over
yeah right
here
a couple things one is the client ID of
this external client
I need the server application ID so I'm
this client calling that server and of
course we're just always going to need
this 10 ID so we have the tenant ID here
as well
now in order for my application to
acquire tokens I'm going to need to pull
in some additional libraries or Library
I should say in this case I'm going to
be using the
microsoft.identity.client library so we
had identity.web that was for the API as
a clients I can use
microsoft.identity.client so I'm
acquiring a token as a client to call
something else
now if you've ever used Azure ID to
secure like your database or other
things inside of azure it's using these
libraries underneath the covers as well
so we're we're using these libraries now
directly to acquire tokens as opposed to
being kind of transparent underneath the
covers from calling these other Azure
resources
all right so we've got our client ID
there next thing we need to do is modify
our configuration
and this is going to be a ton of stuff
here
that
so uh a few things here one is we need
to um
configure the Microsoft identity client
to be able to call Azure ID to acquire
our tokens so that's what we see here
we're using this confidence confidential
client application Builder and what it
gives us is this object called a i
client confidential
client application that is the thing
that we'll be using to acquire a tokens
so it's a an API that wraps up all the
oauth 2 business behind the scenes to
eventually just get a token out from the
other side
all right
the next thing we'll have is
for each individual client we're going
to be calling I need to know like what
is the application or server ID of
whatever that is and I'm going to be
using the uh the typed HTTP client way
of calling these apis so each of my apis
has this interface
feels like we're back to WCF again but
has this interface to Define all the
different API endpoints to make it easy
to call our apis and then our client is
then just like call you know git from
Json async slash to do items uh get put
post and delete
so my application will call this object
to make the HTTP class behind the scenes
and then the last thing we need
is middleware in that API client so that
every time I make a call to the API it's
going to acquire a token from me
transparently behind the scenes so I
don't want all my application code like
oh I need to get this Tok I need to get
this token so in this case we'll be
using handlers for HP clients to
transparently get that's uh
transparently get that token for us
underneath the covers so This
Confidential client application off
Handler
takes our client our confidential client
application so the thing we registered
earlier
and then down here
it's going to say I'm going to acquire a
token for a client and the Scopes it's
going to acquire for are just the
default Scopes it just means I don't
want any specific one just give me all
the ones that I've uh I've assigned to
me
and so it gets all those
gets an access token and then applies
that access token as a bearer token as
an authorization header
so my client code
over here and these workers
is just getting the to do items clients
which is the type HP clients and just
makes a call to say git
but in this code here you don't see any
authorization header or business that
was all done for us via that middleware
all right so the next piece I need to do
is I've got all the client code here I
need to then assign the roles for this
new external client to my server
application
so back in our infrastructure code
let's go over to our server
we'll create some methods here we have
one method already to the Azure ID
resources we'll also do one for the
external clients
now this external client what I'll be
testing here is this this client does
not have access to all the roles and
only has permissions to do reads and so
I'm putting that that kind of a
responsibility of you know who should
have access to what roles I'm really
saying that's the server's job to
determine all that so that's why it's in
This Server class in my infrastructure
code
then we'll need to call this assign
roles over here
so we've already assigned the group
all right
so
let's go ahead and run the server
and run our clients
and see what happens
there's my server I can authorize
against that let's go and run the
external clients
and this again is just a Daemon
application that has background workers
making API calls all right it's already
making API calls it's making two API
calls though one is just to the get and
one is to the put
it does not have
authorization for the put so that's why
you see this 403 Forbidden I don't have
that role assigned to my principal to be
able to make that call so the server is
going to say you don't have you don't
have authorization for the resource
because you don't have that token let me
go ahead and grab that token here
and go to jot Ms again
and sure enough
we've only been assigned the read role
not the right role
the other thing that you could see in on
site here like this is the the audience
which is still Visual Studio this is the
tenant ID over here and then over here I
think one of these IDs is the clients
and then one of these IDs is going to be
the server itself
so it's doing all that Force
transparently underneath the covers when
I call the API it's checking all those
values and then finally the
authorization for that attribute is in
checking that role
all right
so that's our external clients
using client credentials with a client
secrets
the next thing we need to do is the
Azure client so something deployed
inside of azure now we could go this
exact same route
which is to say let's go ahead and
create our own client ID and clients
you're going to put inside of there but
there are some Azure ID resources that
make our lives much easier to be able to
have these kind of principles for things
inside of azure
so that that thing is known as a managed
identity a managed identity is a Azure
defined principle that we can assign to
specific applications to Virtual
machines all sorts of things and then
when my application runs it's running
under that identity of the managed
identity versus something I just made up
over here like this external application
whatever
so
our Azure clients
there we go
let's go ahead and create this thing so
first what we'll need is
uh there it is
we need to create our web application
that's going to be running inside of
azure so that's this web app here
so it's still saying I am going to be
running you know net Azure clients I
also included some configuration to say
Well when I'm running inside of azure I
need to know where the server is and so
I just have some app settings defined as
there foreign
the next thing we need
is an identity for this web application
so this is going to be
a managed identity a user assigned
identity now
everything does run as a managed
identity behind the scenes for you and
like app services and things like that
but I want to be able to manage that
identity myself and so I'll be creating
my own user assign identity which then I
will then assign to this web application
so here I'll modify my web application
definition to say this is your identity
this is really ugly Kobe that's just
because the this arm template garbage is
sometimes really ugly so anyway I am
telling the web application that you are
going to run as this managed service
identity
and then finally I'll go ahead and
output all these things down here so
here's my user assigned client ID uh the
principal ID and the host name that I
can then spit out when I run my palumi
up code
next I need to assign the roles for this
client to that server
but I'm not going to be assigning the
application
I'm going to be signing the managed
identity
so over my server
one more method to assign roles
I take in the clients and it's going to
be assigning
the reason the right permission for the
user assigned identity principal ID
so
the managed identity is now going to be
assigned those permissions
finally over here when I I'm assigning
my roles I'll go ahead and call that
assign roles method so here I have
assigning the roles to my local Dev
group the external clients and the Azure
client
now this API this Azure clients
is kind of a cheat so what this API is
is a mirror image of the Azure or the of
the server API it's got the same exact
controllers the same exact methods
except
instead of like doing the real calls
it's calling into our clients so it's
making API calls so it's an API calling
API this is meant to represent our BFF
it's an API that calls other apis but
it's going to be using the manage
identity to identify itself and
authenticate against Azure ID
so I need to tell this API now how to
make those calls and how to uh how to
authenticate
so for this we're going to be using
another
Library that's azure.identity
so Azure that identity is a library that
you use whenever you want you want to
use managed identities to make other API
calls so if you're if you're deploying
an app inside of azure that calls into
Azure SQL it's going to be using this
Library underneath the covers to use the
managed identity to authenticate to get
a token to call out to SQL
the next thing we need to do is
configure this so let's go into our
startup
oh
configuration first
so go ahead and
again I need to pull in the client oops
the client ID and the server ID
the client ID is the ID of my managed
identity so when I ran my polymy code
out popped
the client managed identity client ID
and so I grab that value and that's what
I'm going to be putting inside of here
next I need to configure my application
to be able to call those different apis
and it's going to be
uh yes right here
so
for the azure.identity library
we have a little bit different way of
acquiring our tokens and it's using this
concept of a token credential this token
credential is basically wraps up many
different ways of being able to acquire
token one way is using visual studio
another way is using the managed
identity it could also use environment
variables so this token credential using
the default Azure credential wraps all
those different combinations together so
they don't have to configurable visual
Studios this way manage identity is this
way and maybe I'm using environment
variables this way if I'm inside
kubernetes or something or in a
container that's all part of that
finally
we will
add more configuration that is the API
client configuration so this is like
this is very similar to what we saw
earlier of I need adding middleware to
be able to automatically acquire a token
I'm adding these type HTTP clients with
a specific configuration with its
different base addresses and then adding
the middleware for each of those clients
so that when it makes those calls out to
the Azure server it's transparently
acquiring the token now this middleware
is slightly different than the previous
one because it's using the token
credential now
this thing to acquire a token
it says the scope I'm looking for is
again my application ID me oh no I'm
sorry the server application ID and the
default uh roles for that so the dot
scopes
it's going to call git token async and
then out the other side is going to be
our jots
so let's go ahead and run this
I'll run the server
and we'll run our clients
our Azure clients
now I'm running locally
so I don't have a managed identity so
what that default Azure credential gives
us is why if you're not in Azure you
don't have a managed identity we'll just
go ahead and fall back to your visual
studio uh user
so when I make these calls
try it out
execute
this is now using the visual studio
context to say oh right let's go ahead
and use whoever you're logged in as
inside of Visual Studio
so like up here this user up here I'm
signed in is going to acquire a token a
pop on behalf of that user
oh
well I missed something
that's okay we'll go ahead and run now
um oh internet problem of course
always always running on the cloud so
why don't we go ahead and look at the
actual running Azure instance of this
so over here
oh internets
if my internet was actually working
right now then my clients
running as that managed identity would
be acquiring tokens on behalf of that
managed identity to make the calls out
then to my my actual Azure server
um because I'm using managed identities
there I'm going to be using that same
managed identity to secure all my other
agile resources so accessing key Vault
or Azure SQL anything else it's using
that same exact identity
all right
so just to wrap things up
we had our azure
we had our Azure server oh no that's
fine
I don't have one of those connections
anyway
um
we had our Azure server running
completely inside of azure that was
using Azure ID to identify itself as a
resource using application registration
we had an external client using client
credentials flow with a client ID and
client secrets we authorized that client
using the application permissions and
finally the 100 internal to Azure client
here
could use a managed identity to identify
itself and make our lives much easier to
be able to secure against our server as
well as any other Azure resources
so
that was building secure microservices
in Azure again I skipped all the
networking stuff there's a whole bunch
of that too I don't understand any of it
but this was the application aspect of
it of using oauth 2 and Azure ID to
secure different calls inside of azure
if you want to see this example running
I have a GitHub this link down here
github.com Azure ID example that is that
full running application you can use
that palumi to the plume script to run
that against your own Azure subscription
and create those own resources for
yourself otherwise you can find this
slide and the code on my github.com
presentations thank you all very much I
hope you all have a great rest of the
conference
[Applause]