← All talks

OIDC security weaknesses and pitfalls

BSides Oslo · 202337:4249 viewsPublished 2025-07Watch on YouTube ↗
Speakers
Tags
CategoryTechnical
StyleTalk
About this talk
Best current practices (BCPs) for implementing OAuth2 and OIDC have undergone many changes over the years. While following the BCPs it’s still easy to make mistakes and you might end up with a weak or even broken implementation. Based on our experiences performing penetration tests and security reviews, this presentation will show common OAuth2/OIDC security weaknesses and pitfalls. In particular concerning the BFF-pattern and why it is bad practice to use reverse proxy catch-all routing, an OAuth2 client with access to many scopes, together with APIs that do authorization based on just a valid token and scopes. Does your BFF enable authenticated SSRF as a Service? Tobias Ahnoff: Tobias Ahnoff is an experienced developer and architect with focus on application security. He specializes in implementing authentication flows and authorization for web applications and APIs that manage sensitive data. Tobias performs security reviews and penetration tests as part of Omegapoint Cybersecurity Gothenburg, a group of experts in application security. He also gives courses in application security and is an appreciated speaker in OAuth2 and OpenID Connect areas. --- BSides Oslo is a independent, community-driven inclusive information security conference. A part of the global Security BSides network, the conference creates a space for members of the information security community to come together and share their knowledge and experiences. BSides Oslo is intended for anyone working with, studying with or is interested in security.
Show transcript [en]

I'm glad to be here at bides and there will be more on the same topic as the previous presentation so that was how VIP secure their apis and uh the focus was on a mobile uh client this talk will about uh will be about where we use the web browser and uh if you remembered from the previous presentation the log in with um screenshot there H so so imagine if you have a sort of open banking sit or that where you want to log in with all the different bank IDs or support different bank IDs in the Nordic countries then there's a good chance that the client writing are using openly connect and UA to enable that and to drive that uh

login flow and uh if you follow the best current practices for this then you will use a backend for frontend pattern and I will talk more about that later on and this talk is about security weaknesses and pitfalls M mistakes that are easy to make even if you sort of have done your best and know the specs and um yeah I'm toas and um I'm from Omega point gamberg and we do penetration tests and Security reviews but uh yeah me and my colleagues we also work as developers writing and maintaining code and helping teams with application security so together we have a lot of uh strong background in um both attacking and Building Systems with oo

and open connect and uh so we'll start with a little bit of history about around AO and open connect and how we do secure implementations today and um it started out with o 2 there and um there was a lot of sort of custom implementation of oaf login or oaf but but that was lot of weak implementation as well um Facebook and uh Microsoft and so on all have done mistakes use implementing this and uh to sort of address this uh things in the beginning um in open connect was introduced and provided identity and uh login and sessions on top of a and um but then a and open connect was used in high security

environments as well uh and we in Bank banking finance and Healthcare and so on so there was security profiles and uh best current practices and um the most well-known is the uh security profile for financial grade apis but that's applies to uh any business with high security requirements uh and uh then we have the best current practices for for o and I gathered under o 2.1 and uh this is a lot of specs and probably like a two-day workshop at least to uh to uh go through all that uh so for this talk I will give you sort of a two-minute version of how we do secure applications following those specs and uh so so the basic thing here is that if

you have service to service where no user interaction then you use something called oo client credentials and you strengthen that with strong client authentication not just the basic authentication for the client instead you use Mutual TLS and or something called or EVT assertions we saw those earlier the signed like looks like access tokens almost and um then if you do that you can do sender constrained access tokens which they also mentioned in the previous talk and you either you sort of you link the access token to the certificate that was used and uh you can use Ms or something new called depop and of course you should have shortlived access tokens and sort of follow list

privilege and for yeah especially for third party clients within Banking and finance maybe concerning the psd2 directive you should definitely consider reference tokens to not leak information outside your organization and being able to revoke the tokens fast um so that was the service to service and um when we have users then it's more complicated and uh we use the code flow and uh the the AO code flow is when you just want to have consent to delegate authorization to a third party application for instance but when we do login it's openconnect code it's uh yeah it's a similar flow um um and we won't really distinguish between the two the things I will talk about concerns them

both um so and we can since we use this BFF pattern we have a confidential client a backend client this means that we can use the same hardening techniques as we did with the client credentials there uh so we can apply things like strong client authentication and uh send a constrainted access tokens even if the user is using a web browser and uh of course we should follow the best current practice and FY and apply additional protections with the code flow pixie is mandatory par should be used but it's kind of new uh very few supports today um but hopefully in the next year that will be better supported and um yeah so this was the two-minute

version so if we follow all this is the problem solved then are we secure and um ah unfortunately not because in reality many implementations they don't do this BFF pattern so they handle access tokens in the browser in JavaScript fronts which is a very hard environment to secure so it's it's very hard you you can't keep secrets there and so uh so you should avoid having tokens there at all if you can H and most implementations they don't uh bother with client certificates I mean it's quite boring to deal with and keep them rotated and things like that so it means that uh a lot of things happen with just basic client authentication and kind of static client

Secrets perhaps and and then we have the its bar tokens they not send a constrainted uh I mean VIPs do it well as we saw but if you don't do this um uh send us constraint tokens then you can just uh steal a token and use it from whatever you want uh so um and then we have this part not supported so it's it's a so there are a few things here that uh that open up for different attack vectors and um uh we to understand these attack vectors we will start by looking at the implementation um with the 2019 best current practices that's I mean that's ages ago so whoever built apps like that and hasn't

updated so if we look at the so so the the the current best practice there really is a current there so so it's important to stay updated and um if we look at uh how that um a spa here a single page application running in the browser it looks like this we have this uh token service or uh identity provider and um and the token request and the authorization request it all happens through the browser so the token will typically be stored in local storage is a common place to to store the token and then the spa here can just attach the token we saw the authorization header with the barer and the access token there usually a Json web token and

they can call the different apis are and there could be a lot of apis of course in this sort of microservices architecture here we just have two but uh the product API and the order API and what's interesting here uh to get a little bit of context is that of course the logged in user should be able to get the products this user can access not other products um and the login user should also be able to get uh the users orders not orders for other customers and the login user should definitely not be able to use this endpoint get all orders that is meant for system Integrations uh to sort of access all the data in the system in in a in an

easy way uh so so the sort of ultimate attack here is that the attacker can uh execute the get all orders uh caller and and one thing that we should note there is that if you have been following the best current practices from 2019 you have built this way and then you also probably use something called a silent renew uh because access tokens are shortlived and we can't bother users with the logging in every now and then like every fifth minute or so and so then there's something called Silent renew and that means that the um Spa there will silently in the background call the token service for new tokens and it will get new tokens because it

can present a session cookie to the Token service which also sometimes referred to a single sign on cookie because that always so enable single sign on though um yeah so so they attack there to get all orders how can we get a token to get all orders and uh this is an a way to steal tokens um uh cross scripting is um is common it's less common these days but in an old application like this from 2019 or something it's it's a good chance that we have a cross-side scripting vulnerability and if we can inject code running in that application there are other ways to inject code like uh supply chain attacks and things like that but

uh we discussed cor of scripting here uh then that code can do the same the same things that your application code can do that means it can silently renew tokens and send those tokens to the attacker server and uh from the attacker server we can uh access the apis just like the application would and um so so that is of course not a good thing and uh and uh one thing to note there is that there are might be clever attempts to hide tokens in the front end but uh it's it's you you can't really can't do that and if you want to look closely on this with the nice demos then Philip Dick had a

great presentation on NC Security earlier this year that I can highly recommend available on YouTube um yeah so how can we fix this or make it harder at least um of course we we refactor to the best current practice of today and this means introducing the uh backend for front end pattern and um then it looks like this and we have introduced this back end which is a dedicated API for the front end application and it uh holds the session and it will also holds the access tokens and the spa is basically exactly the same it's now served from the back and for front them and um all the JavaScript code quite complex code uh has been removed instead we have

moved that code backend so everything um the token request now goes from the back end to the Token service this means that this back end is uh the client now is a confidential client not a public client running in the browser so we can use things like Mutual TLS and uh send a constrainted access tokens and things like that and um and another thing to note there is that we now secure that uh session with a session cookie that is properly configured um you could of course do mistakes here and have an insecure session but that's not the issue in this this stock so it's h it's it's secure and um and then uh we have

also introduced to to yeah to really risen the bar here we have applied infrastructure protection as well so which we missed earlier so because now we have this back end front and the other API said the backend apis they don't need to be public on the internet anymore so we can um introduce a Gateway or firewall and make them internal which is great because you shouldn't really expose internal apis on on the internet and uh of course this picture we don't have the infrastructure protection in front on the BFF there it could be a web application firewall and so on but uh attackers are quite good to bypass those so so yeah so that's not in the in the

picture and um so so this is um what we have and um it seems pretty bulletproof right it's it's very hard now to to get all orders and there are no tokens in the front ends to steal anymore but uh the the cross scripting vulnerability it still exists it's it's really hard to keep a a front and uh secure from Cross scripting over time so and and with if the attacker can um inject code in your application then uh they can now do session writing of course so so they can do anything the user can do with the user session there uh so so that's it's a more limited attack than than previous but it may still be quite bad so so what

can we do if we can do session writing in this context uh well it's hard to tell without uh proper testing perhaps pen testing or your own security testing and uh we can start by looking at the requirements for this access model that uh uh we have here and uh the first here is that we should be able to get product one because the user has access to product one that is a success we should be able to get the orders and our own orders not other customers orders quite easy and then we have this orders all and it's a little bit more we need to think about that a little bit more so should return all orders but only if the

caller is authorized for this all access and um to to um make this maybe a little bit easier to test we can uh write rewrite this as two test cases um should return orders if the caller is a system integration should not return any orders if the caller is a logged in user and that's typical that's the attack so it's it's really a good thing to have those negative test cases for possible attacks because that is what the attacker tries to do so and if we run those on our implementation saw earlier we have all the defenses we have followed the best current practices but unfortunately the last one fails here we're actually able by just changing the route uh and uh

accessing still accessing the orders all endpoint even if it's not exposed on the internet and uh that's surprisingly if you ever end up here and uh so and not good so how did that happen What enables this attack and if we look closely into this uh this picture uh we we will start looking at the the bffr what does it do it um it it it's rout and we see the stars there so uh so so a default configuration for many reverse proxies or gateways like this is to look something like this they have a white list for uh hosts which they can route to but often it's sort of default cat all routing there with the Stars which means

that they will route to anything that you pass in there not just the ones that the backend for frontend should be reaching and since the backend frontend can reach the host it could it should make calls to any endpoint there and um yeah so so so that's that's not good we we have the stars there um and besides proxying request which what does else does the back and front and do ER because I mean those were public before so so it can't be that bad but it also attaches the access token connected to the user session uh so so that means that you can hit any API inside here with a valid access token it may not be

valid for that Endo you're hitting but does your average API do proper Access Control well the stats are against you but because if you look at the top five here it's all almost all broken off in some way so so it's a pretty good chance that the API here it sees this token and it will accept the call and um but there are actually Four issues here for this attack to succeed and um if we look at that we need to access a low privilege session in a larger organization it's quite likely that during some point the attacker will be able to uh get hold of an account or misuse a session in some system you can also sign up to get a low

privilege user so so that's really not an obstacle and um then the BFF here it needs to have access to the APA hosts on the internal Network and especially in the cloud perhaps but also on Prem it's quite rare to see network segmentation between the backend front end and the apis maybe you have Network segmentation to the databases and so on but but between those web hosts it's it's rare to see network segmentation so uh so that's quite likely that you can access and and especially since the this microservice architecture here it sort of maybe drives that the BFF should be able to reach every host to get some endpoints and and you mix host

uh system integration points endpoints are hosted uh together with the end points for users uh because it's easier to maintain and deploy and develop and so on so you can't really count on network segmentation to to solve this H and then we have this catch all routing um and that's just a common default so it's a pretty good chance that that's in place as well and finally we have the authorization bugs in the apis which also is likely so it might seem that a lot of things should be in place for this attack to succeed but in reality it's not that unlikely and it's definitely a risk that you should uh consider and so how could we mitigate

all this well as um always this guiding principles here zero trust Le privilege and defense in depth will we sort of guide us in the right way and um talking about how we should apply this for a system like that is talk of its own so we'll focus on two things here uh proper Access Control in API and uh the routing here with with the BFF that it only should route valid requests and if we start with the BFF routing that's kind of easy to fix but it's boring and maybe hard to maintain H but there really no is no way around having a strict allow list to to close this possibility for an attacker uh to uh hit

end point you're not supposed to H and don't try to be clever here and introduce sort of patterns and regular expressions and things like that pentesters and attackers are really good at bypassing those kind of clever things so just do do a strict white list or allow list and uh so this solves the problem but um but from the previous slide we should apply defense in depth and Security in multiple layers we shouldn't just rely on the routing here it could be easily misconfigured right so of course we should also handle U the um the API uh authorization so so if we apply this white list um the routing is sold so no stars there

anymore um but so so this API authorization why is it so hard for apis to do proper access control and uh this BFF pattern it's sometimes it's makes it a little bit harder and it concerns the Scopes and I sort of add some challenges to to the apis here and uh so now we'll look at that and uh so if we look at the authorization request that initiates the login flow here with the open and connect and the code flow it it looks like this and it goes through the browser and we have done lot a lot of security and it's quite easy to forget that no matter what we do the attacker would always control this and can change

this but um State redirector client ID they are all validated and it will be a um bad request if if the attacker changes any anything here but the scope here that's by Design the attacker can add or the user uh can add any scope that the client has access to uh and um and and why why is that so bad it's it's sort of by Design but um so if we just add Scopes there so uh because Scopes are easy to misconfigure it's it's it's um hard to keep this lease privilege when you do client configuration you might be reusing a client for different applications for different scenarios for instance you might combine a client where user do

login but also with system integration if you do that that means that a user that is logging in can add the Scopes only the system integration should have access to and then they will get an access token with those Scopes when all this redirects and the login is is done uh so so um and also apis could misconfigure which how they interpret the scope for instance so so keeping the least privilege there is uh is really important and and um uh yeah so we should of course only configure the Scopes and flows uh that the client actually needs and uh try not to mix those uh roles and if you um have high privileged endpoint then it's it could

be quite risky to just base authorization on that the fact that the token is valid and that it has the correct scope you could use something more like perhaps the client ID or or authentication method and and and so on and um and then of course this sounds really weird why should the user and attacker control what Scopes uh are in the authorization request if you have a consent page that makes perfectly sense because then you select the Scopes and that's part of the design but if you're logging in there is no consent so why and uh for that we use par and Par is like this and then the authorization request only has those two

parameters and if any of those are changed then the request will fail so uh the Scopes are sort of pushed from the back end uh and this is a reference to to to those Scopes so so now so now we closes that attack Vector that someone actually changes the the Scopes there uh so that's a good thing but uh not supported by um token Services yet but the RFC is there so uh yeah so so this was uh one part of the scope issue another part here is uh that you might end up with really really powerful access tokens and and and if the access token is very powerful then it's harder for the API to make the right decision

so if we look at what we have here from a little bit of different perspective we uh the back end front here will have an access token in order to provide the user with all the functionality it needs during its session it it must get an access token that has access to all this functionality which means all the Scopes and audiences um and depending on your system it could be all the Scopes you have in your system because it needs to to get user data from uh all those microservices and um so so that could be a problem and it could also looks like this of the Shain pattern here which is a challenge for a implementations and uh

and as you can imagine there can be a lot of Scopes and a lot of access if you just sort of pass along the original token and that token could then become sort of a glorified API key with access to all the apis in in your system and and that might be fine uh you or risk you're willing to take but it could be really catastrophic if for instance the API 3 here may be another organization or much weaker protection because API 3 will have an access token and can start misusing that hitting API 2 and one so uh so so that's one way to to leak tokens um yeah so Scopes design is is

quite hard in larger organizations and worth spending time on and uh one way to deal with this to sort of have more of least privilege for tokens is to um yeah to create a new token uh you have the token for API 1 but API that is not valid for 2 and three so API 1 needs to do client credentials and get a new token and uh we have like this and then we solve this scoping issue because then you only need the scope needed a one and you have least privilege there and uh that's good um one uh thing that you might run into is that tokens get too large for the uh HTTP header and and

that's not a good design because uh then you probably have two powerful tokens and need to sort of redesign fine a good solution to that is not to increase the max size of the HTTP header for the for the web service uh but uh so it solves that problem but it introduces another and um now it's kind of hard to have the traceability or accountability that the user actually initiated this call because uh API 2 that only sees API 1 so to handle both we can use something called token exchange that's also not supported by many token services but but there are definitely a lot of them that do that uh so um then we pass the original token

when we change the token and we will get this act claim in the token that uh provides us with this chain of traceability so we can know how how the request has been uh so this uh handles boats and if if you don't use this then understand the risk you introduce maybe accountability is solved in another way uh so it's not needed or you're comfortable with having sort of global access tokens and uh we should note there that this uh list privilege for tokens it doesn't solve the session riding in any way because the attacker who do session riding in the back and for front end there will of course be able to do anything the US can do it it

this will only limit the risk of leaking a global access token but the session writing uh remains there so with this I have shown how to build uh secure open ID connect implementation and following the uh best current practices and uh it will look look something like this and uh and then we talked about how to avoiding some common pitfalls concerning the routing and the Scopes and how that may affect how apis can deal with authorizations and uh it's time to uh to summarize and um the first thing here is that um please read and follow best current practice for o 2 and openly connect um the F here is this very detailed on guidance and how to

implement things uh so I can really recommend that and there's a version two .0 right now and that's more easier to uh digest than the uh than the first version but uh so that's important so even if security should always be proportional to your business so even if you're not sort of in the healthcare or more finance and have those High requirements then it's easy it's important to understand uh what protections you have and the attack factors that exists concerning those protocols so you know what your so so if you choose to ah I I will stick with barer tokens and that's may be a perfectly good choice for your business but you must understand the risks you

introduce so it's it's quite good to understand those H regardless of what level of security you you're on you're at and uh then of course uh for basically any application uh stop handling access tokens in JavaScript front ends and start using using the back and front and pattern with a strict allow list so we don't so then so this it's a little bit unfortunate we have invested a lot in security here and it's we shouldn't end up with a vector for authenticated server side request forgery by having this wild cards uh routing uh so and then of course proper Access Control in the apis um so uh and we will sort of help to make this easier by following

list privilege both for client configuration and when we do token token requests uh so even if the client has access to a lot of Scopes it shouldn't uh always request tokens with all those Scopes um uh and uh finally when we have a browser uh based application cross scripting is a really really serious problem if we're vulnerable to that because session writing is usually really bad and uh if someone has can run code in your application then they of course can then they can always do session writing so uh yeah that was um it for me any [Applause] questions questions

hi thanks for the presentation um my question is if we store access tokens for example in Secure HTTP only cookie would that mitigate majority of the risks that you mentioned about handling access tokens in JavaScript front ends yeah yeah in in a way it's it's it's stronger to keep them in the back end but uh but uh storing them in a encrypted uh cookie not reachable from JavaScript is uh means that across scripting can't really access that but having a powerful token on the client means that if you have control over the client then maybe you can get that token so it's better to keep it in the back end but uh if the encryption is strong

then it's really hard to get that token so yeah so because some Frameworks they do that by default net for for instance and so if you have it in an encrypted cookie then you get less State uh issues with the with the back end but but but since we if you want to add things like if you want full control over a session you want to be able to force the user to log out or end the session then you need complete control on the back end anyway so so but if you're sort of in a little bit of lower security requirements then that could definitely be a solution that's good enough and yeah yes so the best current practices

for S Spas also has a um a recommendation if you can't do the uh bff or token service pattern by using web workers what are what are your opinions on that using web brers to in order to keep tokens more secure in the uh in the spa correct yeah yeah that's um it's supp it's very hard to secure the the JavaScript front end and uh and um if you can run uh code there you can use this silent renew to get the tokens and so on so so the the tokens are less protected in the uh in the front end than in the back end and the I think the the recommendations for high security

environments are quite clear that you shouldn't have tokens in the front end even if you try to hide them in in web workers and things like that I really recommend Philip the Rick's presentation from NC Security on on that topic any other questions looking up at the balcony anybody don't let your BFF be a vector that's it all right everybody's everybody's got it thank you very much oh here what do you see for the future um well the concerning web applications I think the sort of the protocol has sort of settled and I think maybe there won't happen much but concerning mobile applications and how you do a good user experience logging in on that and also utilizing the

possibilities to do biometric login and and the the fact that you have a really powerful device in your hand sort of the the tou flows and the VIPs there and we have the web both and uh so I think there will be Integrations with that that will sort of change things and there are some new parts uh concerning those flows that probably will uh happen during the next years so I think the integration with web both then will become more common and and clearer uh but uh yeah anybody else I have a question I'm wondering uh if there's anybody who's into bug Bounty and uh wondering uh how they could look for this stuff do you have any tips for

a quick and efficient uh Discovery and validation of these types of issues yeah um uh we often work with the ports we here and the Barb suit tool when we do penetration test and they have excellent labs and on how to sort of attack and and explore attack vectors around concerning this so um that's that's a good place to start uh and um otherwise the specs there and they have an excellent threat model uh around oo that I highly recommend reading and that could give you some insights on how to attack those kind of systems do ethical hacking of course it's very important yep all right if there are no more questions then let's give a big thank you to tobas thank you