How to achieve client validation in iOS? - ios

How to verify if the API being hit is from the actual application and is not going through any MITM attacks.
I understand SSL certificates can be used to achieve transport level security and the app can be sure it is taking to the correct server, but how can I attain the same thing from app side.
I just want to make sure that only my app is hitting my services and the hit is not coming from somewhere I don't trust.
Thanks

Have a look at SSL again - it offers client certificates, for example, to do so. Yet, this only shifts the problem as an attacker might use the same mechanism the apps use to get certificates. (An shared API token is often considered okay as well and much easier to implement.)
In general, you cannot achieve a guarantee for that. You might get a good result by issueing certificates based on user authentication by external means (e.g. make users put in their user names and passwords) or make it hard for adversaries to abuse your API by using reverse turing tests (e.g. completely automated programms to tell computers and humans apart, aka CAPTCHAs).

The same way that the client validates the server based on its server certificate, SSL supports the server issuing client certificates and requiring communication to be signed with that specific certificate.
With this approach it comes down to possession of the certificate rather than, say, knowledge of a password. Which in the case of mobile is problematic, because an attacker can more easily gain physical access to your device and read your app's documents. So take care to store your keys in your keychain.
Also, your method of handshaking with your server and asking it to issue a client certificate becomes a security bottleneck. An attacker could, since she has physical access to the device, sniff the traffic and easily figure out the API calls needed to get the server to issue the proper certificate.
Read Apple's business oriented document on security in iOS here.

Related

How to ensure that my app's backend API is only accessible by the app itself?

My mobile app is using an HTTP-based API with endpoints that aren't hard to figure out, such as https://<domain>/api/config or https://<domain>/api/login.
So someone could create an account in the app, then use the credentials in some request-making desktop app ("rogue client") to send requests to /api/login and then, after "logging in" with my bearer authentication scheme, go on to other endpoints to see what data is being sent from there.
Such attempts could potentially let people peep into some sensitive data about other users that should only be accessible internally by the app alone.
What would be an established approach to improve my app's security in guaranteeing that any data sent from my backend API is accessible by the app only?
Specifically for iOS apps, are there any frameworks to achieve this?
My backend is Nginx & Django.
MAPPING AN API
My mobile app is using an HTTP-based API with endpoints that aren't hard to figure out, such as https:///api/config or https:///api/login.
All it's needed to map all the API endpoints being used by your mobile app is for someone to install your mobile app in a device they control and proxy the requests through a proxy, like the mitmproxy:
An interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.
BEARER AUTHORIZATION TOKEN EXTRACTION
So someone could create an account in the app, then use the credentials in some request-making desktop app ("rogue client") to send requests to /api/login and then, after "logging in" with my bearer authentication scheme, go on to other endpoints to see what data is being sent from there.
Yes you can create the account in the app and extract the bearer authentication token, and for this you can continue to use the proxy approach I mentioned to map all the API endpoints. You can read this article to see how I use mitmproxy to extract an API key, therefore applicable for your bearer token scenario.
The mitmproxy allow us to intercept, manipulate and replay requests on the fly or at any point in time, therefore an excellent tool to poke around your aPI and extract all data while you use the mobile app as a normal user.
SENSITIVE DATA ACCESS
Such attempts could potentially let people peep into some sensitive data about other users that should only be accessible internally by the app alone.
Well here it seems more like a design problem of your mobile app and backend, because a logged user should never be able to access API endpoints as another user.
Also you need to ensure that each API endpoint strictly returns only the absolute necessary data for the mobile app do what it needs to do. Unfortunately more often then not developers have fat API endpoints that give away a lot of info, and then its up to the consumer to filter the data it needs. Don't do this, instead using roles to authorize what amount of data each logged user as access to in each API endpoint, therefore allowing for more or less data to be sent back in the response accordingly to his role.
Another thing to keep in mind is that developers tend to do too much business logic on the client side, and this approach also leads to fat APIs and to leak data that could be kept in server side if the API was the only one responsible to perform that business logic. Try to design your mobile apps to be as dumb as possible, and make them delegate to the backend all the hard work. This approach also as the advantage of making easy to fix bugs without needing to release a new mobile app.
IMPROVE API SECURITY
What would be an established approach to improve my app's security in guaranteeing that any data sent from my backend API is accessible by the app only?
Well you bought yourself a very hard challenge to overcome, but while hard is not impossible to achieve a solution that allows your API server to have a very high degree of confidence that the requests is receiving are indeed from a genuine instance of your mobile app.
So it seems that you want to lock your API server to only accept requests from your mobile app, and if that is the case then please read this reply I gave to the question How to secure an API REST for mobile app? for the sections on Securing the API Server and A Possible Better Solution.
Specifically for iOS apps, are there any frameworks to achieve this?
If you have read the reply I linked above, then you know by now that you should employ security in depth, by using as many layers as you can afford, being the most effective of all the Mobile App Attestation concept.
Bear in mind that has you add more security layers, more time consuming will be for an attacker to overcome all of them. This also raises the bar for the skill set necessary for an attacker to have in order to bypass all of them, thus putting at bay scripts kids and seasonal attackers.
By the way don't forget to always apply strong code obfuscation techniques to your code base.
DO YOU WANT TO GO THE EXTRA MILE?
In any response to a security question I always like to reference the excellent work from the OWASP foundation.
For Mobile Apps
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
The correct way is to use App Attestation
App Attest Flow
It is a cryptographically secure way to make sure your app is the thing which is accessing your API and not something else.
Apple has an App Attest service. Some docs are located here:
https://developer.apple.com/documentation/devicecheck/establishing_your_app_s_integrity
https://developer.apple.com/documentation/devicecheck/validating_apps_that_connect_to_your_server
Here is the best practice of using JWTs.
On the client-side, you create the token (there are many libraries for this), using the secret token to sign it.
You pass it as part of the API request, and the server will know it’s that specific client because the request is signed with its unique identifier
Edit: Based on comments and discussions, reaching to full security is not possible, But you can make it harder using the above blog post practice.

How can I ensure the integrity of my iOS app?

I have the requirement that the signature of my Swift iOS app has to be checked.
I think it is only relevant for jailbroken devices as iOS checks the integrity by itself.
I couldn't find much on the web - most libraries/snippets have not been updated for 5 years.
My current approach would be to calculate the app signature (C-Code) and compare it with an array of signatures that have been loaded from the server. An array because to support multiple versions of the app.
Any ideas or comments on this approach? Maybe it is not relevant anymore for Swift?
Here are some resources that would inspire my solution:
https://github.com/olxios/SmartSec_iOS_Security
https://github.com/project-imas/encrypted_code_modules/blob/master/ecm_app_integrity_check/ecm_app_integrity_check/app_integrity_check.m
Your Current Approach
My current approach would be to calculate the app signature (C-Code) and compare it with an array of signatures that have been loaded from the server.
I need to alert you for the fact that in a rooted phone the attacker will be able to intercept your code at run-time and modify its behavior, this means that your logic to detect the signature is ok will always return true. They do this by using an introspection framework like Frida:
Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.
Your Requirement
I have the requirement that the signature of my Swift iOS app has to be checked. I think it is only relevant for jailbroken devices as iOS checks the integrity by itself.
Well if this requirement have the intention of only protecting your app from running in a rooted device, checking the signature of the app is not enough, once the device is rooted, any app on it can be easily manipulated, as I already mentioned. Protecting an app from attacks on the device itself is a daunting task, and is like playing the cat and mouse game with the attackers, by trying to keep ahead on the game. You will need to use in app protections to detect if the app is running in a jail-broken device, have an introspection framework attached, is running in an emulator, if a debugger is attached, etc. This is a never ending game with the attackers and they have a huge advantage, they can dedicated all their resources and time to break your app, if its worth it for them, but you may not have the same human resources, time and money to invest in this game. No matter how you decide to play the game you can always resort to the Apple Device Check API to mark in the API server that a specific device is not trustworthy.
In case the requirement to check the iOS app signature is more in line with protecting the API server from receiving requests from an iOS app that is not the genuine one you have uploaded to the Apple store, then a better solution may be possible, and is known by the the name of Mobile APP Attestation. So if this is also in the scope of your requirement you should keep reading, otherwise just skip it.
Before I dive into the Mobile APP Attestation concept I would like to first clear a misconception about WHO and WHAT is accessing an API server.
The Difference Between WHO and WHAT is Accessing the API Server
To better understand the differences between the WHO and the WHAT are accessing an API server, let’s use this picture:
So replace the mobile app by web app, and keep following my analogy around this picture.
The Intended Communication Channel represents the web app being used as you expected, by a legit user without any malicious intentions, communicating with the API server from the browser, not using Postman or using any other tool to perform a man in the middle(MitM) attack.
The actual channel may represent several different scenarios, like a legit user with malicious intentions that may be using Curl or a tool like Postman to perform the requests, a hacker using a MitM attack tool, like MitmProxy, to understand how the communication between the web app and the API server is being done in order to be able to replay the requests or even automate attacks against the API server. Many other scenarios are possible, but we will not enumerate each one here.
I hope that by now you may already have a clue why the WHO and the WHAT are not the same, but if not it will become clear in a moment.
The WHO is the user of the web app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
OAUTH
Generally, OAuth provides to clients a "secure delegated access" to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The third party then uses the access token to access the protected resources hosted by the resource server.
OpenID Connect
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
While user authentication may let the API server know WHO is using the API, it cannot guarantee that the requests have originated from WHAT you expect, the browser were your web app should be running from, with a real user.
Now we need a way to identify WHAT is calling the API server, and here things become more tricky than most developers may think. The WHAT is the thing making the request to the API server. Is it really a genuine instance of the web app, or is a bot, an automated script or an attacker manually poking around with the API server, using a tool like Postman?
For your surprise, you may end up discovering that It can be one of the legit users manipulating manually the requests or an automated script that is trying to gamify and take advantage of the service provided by the web app.
Well, to identify the WHAT, developers tend to resort to an API key that usually is sent in the headers of the web app. Some developers go the extra mile and compute the key at run-time in the web app, inside obfuscated javascript, thus it becomes a runtime secret, that can be reverse engineered by deobusfaction tools, and by inspecting the traffic between the web app and API server with the F12 or MitM tools.
The above write-up was extracted from an article I wrote, entitled WHY DOES YOUR MOBILE APP NEED AN API KEY?. While in the context of a Mobile App, the overall idea is still valid in the context of a web app. You wish you can read the article in full here, that is the first article in a series of articles about API keys.
Mobile App Attestation
The use of a Mobile App Attestation solution will enable the API server to know WHAT is sending the requests, thus allowing to respond only to requests from a genuine mobile app while rejecting all other requests from unsafe sources.
The role of a Mobile App Attestation solution is to guarantee at run-time that your mobile app was not tampered with, is not running in a rooted device, not being instrumented by a framework like Frida, not being MitM attacked, and this is achieved by running an SDK in the background. The service running in the cloud will challenge the app, and based on the responses it will attest the integrity of the mobile app and device is running on, thus the SDK will never be responsible for any decisions.
MiTM Proxy
An interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.
On successful attestation of the mobile app integrity a short time lived JWT token is issued and signed with a secret that only the API server and the Mobile App Attestation service in the cloud are aware. In the case of failure on the mobile app attestation the JWT token is signed with a secret that the API server does not know.
Now the App must sent with every API call the JWT token in the headers of the request. This will allow the API server to only serve requests when it can verify the signature and expiration time in the JWT token and refuse them when it fails the verification.
Once the secret used by the Mobile App Attestation service is not known by the mobile app, is not possible to reverse engineer it at run-time even when the App is tampered, running in a rooted device or communicating over a connection that is being the target of a Man in the Middle Attack.
The Mobile App Attestation service already exists as a SAAS solution at Approov(I work here) that provides SDKs for several platforms, including iOS, Android, React Native and others. The integration will also need a small check in the API server code to verify the JWT token issued by the cloud service. This check is necessary for the API server to be able to decide what requests to serve and what ones to deny.
Summary
In the end, the solution to use in order to protect your API server must be chosen in accordance with the value of what you are trying to protect and the legal requirements for that type of data, like the GDPR regulations in Europe.
Going the Extra Mile
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.

How do you enforce secure storage of Access Token by your Partner?

In an Open API world, Tokens are the door key (issued to anyone with a valid Client Id and Secret). Tokens allow anybody who has them to access a resource. As such, they are as critical as passwords.
Example: A 3rd party Native App wanting to access your APIs. The app uses the 'Client Id and Secret' to request for an 'Access Token'. This access token to be used for subsequent API calls.
Concern: Usually 'Access Tokens' have a longer TTL. When they are stored in the Mobile App/Client mobile device and if someone gains access to it, they will be able to replay API calls from a different source using this access token and the API URI.
How do you prevent such replay attacks (when access token is
compromised from the 3rd party app) for API calls ?
What secure practice do you follow to allow your consumers/clients
to securely store the 'Access Tokens' ?
In an Open API world, Tokens are the door key (issued to anyone with a valid Client Id and Secret).
I like this analogy :)
Tokens Importance
Tokens allow anybody who has them to access a resource. As such, they are as critical as passwords.
Well even more critical, because they control access to the API, thus an automated attack with a stolen token can ex-filtrate all the data behinhd that API in a matter of seconds, minutes or hours, depending on the size of it, and if rate limiting or other type of defenses are in place or not, and this as a name, Data Breach, and fines under GDPR can be huge, and may even put the company out of business or in serious difficulties.
Access Tokens with Refresh Tokens
Example: A 3rd party Native App wanting to access your APIs. The app uses the 'Client Id and Secret' to request for an 'Access Token'. This access token to be used for subsequent API calls.
Concern: Usually 'Access Tokens' have a longer TTL. When they are stored in the Mobile App/Client mobile device and if someone gains access to it, they will be able to replay API calls from a different source using this access token and the API URI.
The access token should be at least short-lived, and the client, mobile app or web app, should never be the ones requesting it to be issued, instead their respective back-ends should be the ones requesting it to the OAUTH provider, and use the refresh token mechanism to keep issuing short lived tokens, that should be in the range of a few minutes. This approach limits the time a compromised token can be reused by malicious requests.
So I would recommend you to switch to use refresh tokens, that will keep the access tokens short lived while refresh tokens can be long lived, but in the hours range, not days, weeks or years.
Example of refresh tokens flow:
Sourced from: Mobile API Security Techniques - part 2
NOTE: While the above graphic belongs to a series of articles written in the context of mobile APIs, they have a lot of information that is also valid for APIs serving web apps and third party clients.
By using the refresh tokens approach, when a client request fails due to an expired short lived access token, then the client needs to request a new short lived access token.
The important bit here is that the refresh token should not be sent to the browser or mobile app, only the short lived access token can be sent, therefore your third party clients must kept refresh tokens private, aka in their backends, therefore they MUST NOT send refresh tokens from javascript or their mobile app, instead any renewal of the short lived access tokens MUST BE delegated to their backends.
This is a good improvement, but this only identifies who is making the request, not what is making it, therefore your APIs continue without being able to totally trust in the request they receive as coming from trusted sources.
Oh wait a bit... who and what is getting me confused. Well your aren't the only one, and this is indeed a common misconception among developers.
The difference between who and what is accessing the API server.
This is discussed in more detail in this article I wrote, where we can read:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
If the quoted text is not enough for you to understand the differences, then please go ahead and read the entire section of the article, because without this being well understood you are prone to apply less effective security measures in your API server and clients.
API Replay Attacks
How do you prevent such replay attacks (when access token is compromised from the 3rd party app) for API calls ?
Well this is a very though problem to solve, because your API needs to know what is making the request, and it seems that now is only able to know the request was made in the behalf of some who.
For a more in depth approach on mitigating API replay attacks you go and read the section Mitigate Replay Attacks from this answer I gave in another question:
So you could have the client creating an HMAC token with the request url, user authentication token, your temporary token, and the time stamp that should be also present in a request header. The server would then grab the same data from the request and perform it's own calculation of the HMAC token, and only proceed with the request if it's own result matches the one for the HMAC token header in the request.
For a practical example of this in action you can read part 1 and part 2 of this blog series about API protection techniques in the context of a mobile app, that also features a web app impersonating the mobile app.
It has some code examples for the HMAC implementation, so I really recommend you take a look into, but bear in mind that HMAC only makes it a little more difficult to crack, not impossible.
So this is a very hard problem to solve when the access token belongs to a web app, but it's doable in the case of a mobile app that uses a Mobile App Attestation solution, and this is described in this section of another article I wrote, from where I will quote the following text:
In order to know what is sending the requests to the API server, a Mobile App Attestation service, at run-time, will identify with high confidence that your mobile app is present, has not been tampered/repackaged, is not running in a rooted device, has not been hooked into by an instrumentation framework(Frida, xPosed, Cydia, etc.), and is not the object of a Man in the Middle Attack (MitM). This is achieved by running an SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device it is running on.
For defending your API when used by mobile apps I recommend you to read the sections Securing the API Server and A Possible Better Solution from this answer I gave for the question How to secure an API REST for mobile app? (if sniffing requests gives you the “key”). For web apps I recommend you to go and read the section Web Application from my answer to the question How do I secure a REST-API?.
Storing Access Tokens
What secure practice do you follow to allow your consumers/clients to securely store the 'Access Tokens' ?
Well in web apps all it takes to extract any token is to hit F12 and look for them, but in mobile apps you need to reverse engineer them.
For a mobile app you can stat by looking into the repository android-hide-secrets to understand the several ways of hiding them, where the most effective is to use native C code, by leveraging JNI/NDK interfaces provided by Android. You can see more real use demo apps using this approach in the repo currency-converter-demo and the app for the shipfast-api-protection-demo. For example see here how configuration is loaded from the C code, by using JNI/NDK approach. But bear in mind that while this makes very hard to reverse engineer statically the mobile app binary to extract secrets, it doesn't provide any security from an attacker to go and use and instrumentation framework to hook into the code that returns the secret from the C code, or to perform a MitM attack to intercept the requests between the mobile app and the backend, thus getting hold of the secret you protect so well.
Mobile apps can solve this by using a Mobile App Attestation solution to not have any secrets at all in their code, therefore if you have read the link I provided previously for defending your API when used by a mobile app, then you will be already more familiar with how a Mobile App Attestation works, and be able to better understand why you may want to have your clients using your API like this:
So your API would be sitting along side the ones already in the APIs section, and the secret to access it is no longer in the public domain, instead is safely stored in the Reverse Proxy vault. To note that the green key is provided during runt time by the Mobile App Attestation service in the cloud, and the mobile app doesn't know if is a valid or an invalid JWT token. If if you have done yet, please go and read the link I already provided to the other answer, so that you can understand in more detail how the attestation works.
In conclusion this approach doesn't benefit only your API, because it also improves the overall security for the mobile apps of your clients.
GOING THE EXTRA MILE
As usual I am not able to finish a security related answer without recommending the excellent work of the OWASP foundation:
The Web Security Testing Guide:
The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.
The Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

iOS API Key: Is there an actual safe way to secure your API key when making http requests?

Currently, I am getting an API key from the server after logging in and using it to make http requests. I currently store the API key in the iPhone app's database. However, I've heard that I should store it in a keychain from a colleague. So, I searched on Stackoverflow and seen questions regarding this. It seems this isn't really a secure way of storing API keys at all.
Secure keys in iOS App scenario, is it safe?
In iOS, how can I store a secret "key" that will allow me to communicate with my server?
I don't know a way to stop hackers from reverse engineering to get the API key from the iOS app. A user on StackOverflow basically said it will only overcomplicate things for little to no benefits.
I need to find the post, but someone recommended to just make sure you're making a secure API request (SSL certificate) and you have a way to remove the API key if someone is hacked.
As already pointed out by #jake you should use a token tied up only to the user instead of an Api Key for all users, but other enhancements can be done for further protect your App when doing the http requests.
The user token can be a signed JWT token and then you can enhance the security of the communication between your server and the App with Certificate Pinning in order to protect against Man in the Middle Attacks.
Other techniques like the use of OAUTH2 and hiding secrets can be used to enhance the security of your App and you can read more about it here.
Keep in mind that Certificate Pinning can be bypassed by hooking frameworks such as Xposed that contain modules specific to bypass the pinning, but still another layer of security that you should not discard once it will increase the effort necessary to hack your App on the device and will protect your App against Man in the Middle Attacks.
For ultimately security between your App and the back-end you should use an App integrity attestation service, that will guarantee at run-time that your App was not tampered or is not running in a rooted device by using an SDK integrated in you App and a service running in the cloud.
On successful attestation of the App integrity a JWT token is issued and signed with a secret that only the back-end of your App and the attestation service in the cloud are aware and on failure the JWT is signed with a fake secret that the App back-end does not know, allowing this way for the App back-end to only serve requests when it can verify the signature in the JWT token and refuse them when it fails the verification.
Once the secret used by the cloud attestation service is not known by the App it is not possible to reverse engineer it at run-time even when the App is tampered, running in a rooted device or communicating over a connection that is being the target of a Man in the Middle Attack.
You can find such a service in Approov that have SDKs for several platforms, including IOS. The integration will also need a small check in the App back-end code to verify the JWT token in order the back-end can protect itself against fraudulent use.
JWT Token
Token Based Authentication
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
Certificate Pinning
Pinning is the process of associating a host with their expected X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is associated or 'pinned' to the host. If more than one certificate or public key is acceptable, then the program holds a pinset (taking from Jon Larimer and Kenny Root Google I/O talk). In this case, the advertised identity must match one of the elements in the pinset.
OAUTH2
The OAuth 2.0 authorization framework enables a third-party
application to obtain limited access to an HTTP service, either on
behalf of a resource owner by orchestrating an approval interaction
between the resource owner and the HTTP service, or by allowing the
third-party application to obtain access on its own behalf. This
specification replaces and obsoletes the OAuth 1.0 protocol described
in RFC 5849.
Disclaimer: I work at Approov.
A more secure mechanism would be to return an authentication token on login. This authentication token should be unique to the user. If you have proper authorization and security mechanisms on the backend (to mitigate DDOS attacks, injection attacks, users accessing other user’s data, etc) then who cares if they get their authorization token from the keychain or wherever it is stored? Since the authentication token is tied to their account you could just invalidate the token so it stops working if the user is malicious. And you could even disable their account altogether if you have the right mechanisms in place on the backend.
Many of the security mechanisms can be automated on the backend. Platforms like AWS can easily be configured to automatically disable accounts that are doing certain malicious calls to your backend.

What if any are the downsides to using the resource owner password credential flow when the app and api are first party?

I'm just starting to learn about Identity Server, OAuth 2, and OpenId Connect. While doing so I've spent some time looking over the different OAuth flows and their applications. I understand the risks of using the Resource Owner Password Credential flow when the client is 3rd party or not trusted. However, I haven't really been able to find much on its use when the client(mobile app) and api are trusted 1st party. What are the potential risks of using this flow in this scenario? If you could point to specific security vulnerabilities that would be very helpful.
Thanks!
If you are talking about exactly the following...
Your own Mobile App (using trusted libraries)
Collects User Credentials (as if they were logging on your website, assuming you have one)
Sends them over TLS to your Auth server
Returns the normal token response if correct
Then I would argue there is no security penalty, at least, it is no worse than using username/password auth in the first place.
However, there is a wider problem with mobile authentication of this nature.
There is no way to tell that it's your app sending the requests, this applies to all OAuth2 flows (even if you use a more secure flow, the User can simply pull apart the mobile app and extract the credentials).
There are some features from both Google and Apple that attempt to fix this problem, but I'm not sure how mature or secure they are at the moment, it might be worth looking into.
So you are relying on the User to not get tricked into installing a fake app, however, this lands under social engineering and it does apply to all OAuth 2 flows.

Resources