I have worked with public API's in only one small project, but I recently learned that if one were to distribute a project with API keys inside this is a security risk.
Seriously speaking I want to congrats you for already know this so earlier in your career, because believe you or not, a lot of senior developers are still misinformed or unaware of the security implications for distributing an API key.
One of the main causes that leads to all this confusion about API keys, that many don't even realize, is that a developer needs to be aware about the difference between WHAT and WHO is accessing the 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:

The Intended Communication Channel represents the mobile app being used as you expected, by a legit user without any malicious intentions, using an untampered version of the mobile app, and communicating directly with the API server without being man in the middle attacked.
The actual channel may represent several different scenarios, like a legit user with malicious intentions that may be using a repackaged version of the mobile app, a hacker using the genuine version of the mobile app, while man in the middle attacking it, to understand how the communication between the mobile app and the API server is being done in order to be able to automate attacks against your API. 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 mobile 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 original version of the mobile app.
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 mobile 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 using a repackaged version of the mobile app or an automated script that is trying to gamify and take advantage of the service provided by the application.
Well, to identify the WHAT, developers tend to resort to an API key that usually they hard-code in the code of their mobile app. Some developers go the extra mile and compute the key at run-time in the mobile app, thus it becomes a runtime secret as opposed to the former approach when a static secret is embedded in the code.
The above write-up was extracted from an article I wrote, entitled WHY DOES YOUR MOBILE APP NEED AN API KEY?, and that you can read in full here, that is the first article in a series of articles about API keys.
Reverse Engineering
Surely if someone can reverse engineer the application, they could extract any API keys that are present.
Any secret that is stored in a web application will be easy to extract, just hit F12 in the browser or view page source
and then search for it.
For a mobile app some may think that is much harder, but in fact is also easy, and you can take the route of reverse engineer the mobile apk, like I show in this article How to Extract an API Key From a Mobile App With Static Binary Analysis:
Using MobSF to reverse engineer an APK for a mobile app allows us to quickly extract an API key and also gives us a huge amount of information we can use to perform further analysis that may reveal more attack vectors into the mobile app and API server. It is not uncommon to also find secrets for accessing third part services among this info or in the decompiled source code that is available to download in smali and java formats.
But my preferred method to extract an API key goes for a MitM attack, where I like to proxy the traffic between the mobile app and the API server through the mitmproxy open source tool, and you can learn how to do it in a mobile app on this article I wrote Steal that API Key with a Man in the Middle Attack:
While we can use advanced techniques, like JNI/NDK, to hide the API key in the mobile app code, it will not impede someone from performing a MitM attack in order to steal the API key. In fact a MitM attack is easy to the point that it can even be achieved by non developers.
YOUR QUESTIONS
Question 1
What does an API key contain that would pose a security risk?
More often then not is not about what it contains, but what it represents, and by now you may already understand that it should be used to identify WHAT is connecting to your API server.
In the cases where an API key is a JWT token, then it may or not contain in itself sensitive information.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
So even if the API keys don't contain any sensitive data, they are a security risk from the moment they are used to protect access to resources, because its easy to extract them from client applications and reuse them to perform automated attacks, where the attacker is able to impersonate the API server as being the genuine application(WHAT), and genuine user(WHO).
Question 2
How does one create an application that makes use of public API's and distribute that application without posing a security risk?
The real truth... You can't do it in a web app, because once you release it, any sensitive date on it becomes part of the public domain, once it can be viewed by anyone that inspects the web app with the built-in browser developer tools.
Now in a mobile app you may have a possible solution, that is know by Mobile App Attestation.
Mobile App Attestation Explained
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 xPosed or 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.
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.
xPosed
Xposed is a framework for modules that can change the behavior of the system and apps without touching any APKs. That's great because it means that modules can work for different versions and even ROMs without any changes (as long as the original code was not changed too much). It's also easy to undo.
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.
CONCLUSION
I am a fresh computer science graduate so an explanation of this would be much appreciated.
I hope that I was able to answer your questions in a easy way, and that by now you clearly understand the difference between WHAT and WHO is acessing you API server, because keeping this notion alive in your memory will help you to write much more safer code, no matter if back-end or client side code.
So for web apps you cannot distribute them in a format that keeps the API key safe, therefore you will need to focus your security efforts in the API server.
For mobile apps hope still exists in the form of a Mobile App Attestation solution, that will secure both the mobile app and API server, and without having to deal with false positives.
In the end, the solution to use in order to protect your application and 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.
DO YOU WANT TO GO 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.