<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Max Mansfield</title>
    <description>The latest articles on DEV Community by Max Mansfield (@maxmansfield).</description>
    <link>https://dev.to/maxmansfield</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F871152%2Fc67309d7-7326-4e25-b8c4-4ecfe6d87b2b.jpg</url>
      <title>DEV Community: Max Mansfield</title>
      <link>https://dev.to/maxmansfield</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxmansfield"/>
    <language>en</language>
    <item>
      <title>What I Learned Implementing PKCE for Serverless Zoom Apps</title>
      <dc:creator>Max Mansfield</dc:creator>
      <pubDate>Wed, 09 Nov 2022 18:27:32 +0000</pubDate>
      <link>https://dev.to/zoom/what-i-learned-implementing-pkce-for-serverless-zoom-apps-1k9l</link>
      <guid>https://dev.to/zoom/what-i-learned-implementing-pkce-for-serverless-zoom-apps-1k9l</guid>
      <description>&lt;p&gt;If you’re reading this post without a primer on serverless Zoom Apps I recommend checking out the first post in this Serverless Zoom Apps series - &lt;a href="https://dev.to/zoom/building-serverless-zoom-apps-5ef4"&gt;Building Serverless Zoom Apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post will take a different, more casual, tone and instead focus on what I was able to learn about my creative process while implementing PKCE. Much of the concepts for this post are inspired by a non-zoomie dev.to post from Remo H. Jansen called &lt;a href="https://dev.to/remojansen/strategic-procrastination-and-software-design-559m"&gt;Strategic Procrastination and Software Design&lt;/a&gt;. Check out that post for even more context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security First
&lt;/h2&gt;

&lt;p&gt;When I first set out to write the &lt;a href="https://github.com/zoom/zoomapps-serverless-vuejs"&gt;Serverless Zoom App Sample&lt;/a&gt; implementing proper OAuth, with PKCE and a state verifier, seemed to be the most challenging part of development. &lt;/p&gt;

&lt;p&gt;Why? Well, there’s nothing more important than the security of your app especially when it comes to authorization. Sure, Zoom is the most secure platform in the world but as a developer one wrong move could throw all that security out the window.&lt;/p&gt;

&lt;p&gt;That’s why you’ll see we have a focus on showing security best practices when it comes to the sample applications we publish. It’s critical for your team and ours that Zoom API/SDK credentials are kept secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Road Not Taken
&lt;/h2&gt;

&lt;p&gt;With an eye for security in mind, I quickly found that there was little to no guidance online on how to handle OAuth authorization with PKCE or state verification. Sure, there was some generic information here and there but nothing concrete. Nothing fitting my use case. Nothing you would want to base your best practices app on.&lt;/p&gt;

&lt;p&gt;I could set up firebase user authentication but that seemed like overkill and a lot of complexity for what was supposed to be a quick start. I needed a method to identify a user behind the scenes to store a unique state and verifier on the backend. &lt;/p&gt;

&lt;p&gt;No, I didn’t need to find &lt;em&gt;a method&lt;/em&gt;. I needed to find &lt;strong&gt;the best method&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is PKCE anyways?
&lt;/h2&gt;

&lt;p&gt;Let’s take a step back. Why exactly do I need to implement PKCE? What are the benefits it provides? &lt;/p&gt;

&lt;p&gt;PKCE (pronounced as pixie) is an extension to the Authorization Code OAuth flow that was originally designed for mobile applications that were unable to keep a client secret secure.&lt;/p&gt;

&lt;p&gt;These days, we use it with web development along with our client secrets to prevent CSRF attacks as well as an injection of an authorization code from a bad actor.&lt;/p&gt;

&lt;p&gt;If you want to get into the nitty gritty, I recommend reading the &lt;a href="https://www.rfc-editor.org/rfc/rfc7636#section-1"&gt;RFC Specification&lt;/a&gt; but I’ve pulled some of the important parts out so we can see what exactly PKCE is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This extension utilizes a dynamically created cryptographically random key called "code verifier".&lt;br&gt;&lt;br&gt;
A unique code verifier is created for every authorization request, and its transformed value, called "code challenge", is sent to the authorization server to obtain the authorization code.&lt;br&gt;&lt;br&gt;
The authorization code obtained is then sent to the token endpoint with the "code verifier", and the server compares it with the previously received request code so that it can perform the proof of possession of the "code verifier" by the client.&lt;br&gt;&lt;br&gt;
This works as the mitigation since the attacker would not know this one-time key, since it is sent over TLS and cannot be intercepted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, for each request to authorize we need to create a session for that user so that we can associate their request with a uniquely generated “Code Verifier”.&lt;/p&gt;

&lt;h2&gt;
  
  
  What About the State Parameter?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;state&lt;/code&gt; parameter has a similar use as a code verifier and code challenge except we can customize that parameter to hold whatever data is useful for us. &lt;/p&gt;

&lt;p&gt;In this fashion, not only does it serve as a CSRF protection mechanism but also allows us to pass data to our Zoom App. &lt;/p&gt;

&lt;p&gt;If you’re interested in learning more about using a state parameter I recommend checking out &lt;a href="https://auth0.com/docs/secure/attack-protection/state-parameters"&gt;this guide from Auth0&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Point of Saturation
&lt;/h2&gt;

&lt;p&gt;After even further research I had a few options none of which seemed to fit exactly what I needed. I almost convinced myself to write a signup and login flow at one point. The irony here is that the development for that login code would likely eclipse that of the to-do app it was supposed to federate.&lt;/p&gt;

&lt;p&gt;Frozen from too many choices or perhaps just an inability to find the right solution I decided to postpone the crux of the project - the PKCE implementation. Instead, I would write a basic Cloud Function OAuth implementation and would extend it when I continued my research. &lt;/p&gt;

&lt;p&gt;When I made this decision it felt like a major bump in the road. I was looking behind me trying to decide if it was too late to turn around and go back or if I could manage to make it to my destination.&lt;/p&gt;

&lt;p&gt;Nevertheless, I continued down my path of writing a serverless Zoom App saving the PKCE implementation for when I had everything else sorted out. &lt;/p&gt;

&lt;h2&gt;
  
  
  Security Last
&lt;/h2&gt;

&lt;p&gt;Fast forward a couple of weeks and Zoomtopia is right around the corner. My to-do app is complete and I can rest easy. Not only that but it has passed most approvals and is just awaiting security approval before being published.&lt;/p&gt;

&lt;p&gt;I’m getting ready for bed and planning what I’m going to do for the next day when I remember my recently submitted security review. I begin wondering when I’ll hear back from our team and what sort of feedback I’ll hear from them.&lt;/p&gt;

&lt;p&gt;Concerned that I might not pass my review in time I recollect my past sample applications thinking of the various feedback I’ve had to address in the past and how long that took me. &lt;/p&gt;

&lt;p&gt;I console myself by confirming I have my bases covered and the changes should be quick to address. After all, it’s not like I’ll have to implement any new functionality.&lt;/p&gt;

&lt;p&gt;That’s when it hit me. PKCE! I completely forgot about PKCE and I had done none of the research I planned.&lt;/p&gt;

&lt;p&gt;Bedtime was over it was now time to panic!&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Back to Work
&lt;/h2&gt;

&lt;p&gt;I ran downstairs to my office and immediately started my laptop. Hoping that my security review hadn’t been seen so I could at least spare myself the embarrassment of submitting an insecure app for review.&lt;/p&gt;

&lt;p&gt;For the first time ever, I’m happy to see that no one has gotten back to me on my review. I open up my IDE to work on my to-do app with only panic at the forefront of my mind.&lt;/p&gt;

&lt;p&gt;I looked at my code for a moment, focused my mind on the problem and to my great surprise, I knew exactly what to do. &lt;/p&gt;

&lt;p&gt;It was so obvious! How was I confused before? Well, I’m certainly confused now as I begin writing this PKCE implementation at lightning speed. My first test works. Wait. What?!&lt;/p&gt;

&lt;p&gt;How is this happening? This is working too well. I test some more before realizing it’s only been about 30 minutes but everything seems to be working. I must be sleep deprived, I think.&lt;/p&gt;

&lt;p&gt;I push my changes up to my repository and await the harsh reality that will be the upcoming security review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;If it isn’t clear, my app did indeed pass the security review and you can &lt;a href="https://github.com/zoom/zoomapps-serverless-vuejs"&gt;download it right now on our GitHub&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;So the question is, without putting additional research into PKCE, how was I able to implement it? Well to be honest that would be nearly impossible. &lt;/p&gt;

&lt;p&gt;The key here is that I strategically procrastinated the implementation while accidentally researching everything about Firebase and PKCE along the way. What I mean by this is that even though I wasn’t directly focused on OAuth or PKCE I would mull it over and ponder it as I went through the development lifecycle.&lt;/p&gt;

&lt;p&gt;For instance, when I stumbled across the Firebase Authentication documentation I found myself reading at length about anonymous authentication and the process for anonymous users. Almost without thinking about it, I filed that away for later.&lt;/p&gt;

&lt;p&gt;On another occasion, I’m looking through previous apps to pull sample code and I find myself reviewing my old PKCE implementation. Taking a moment to remember just why PKCE is useful and what it is used for as we covered above.&lt;/p&gt;

&lt;p&gt;Without realizing it, I had spent the last two weeks taking every opportunity possible to learn about how to implement PKCE with a serverless architecture. &lt;/p&gt;

&lt;h2&gt;
  
  
  Strategic Procrastination
&lt;/h2&gt;

&lt;p&gt;It wasn’t until after my security review was approved that I found a name for what I did. After reading the blog &lt;a href="https://dev.to/remojansen/strategic-procrastination-and-software-design-559m"&gt;Strategic Procrastination and Software Design&lt;/a&gt; it became clear that this was part of my creative process when my mind is overwhelmed with a topic.&lt;/p&gt;

&lt;p&gt;As explained by Remo H. Jansen, &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Strategic procrastination involves taking massive action in both physical and mental aspects. You put in extreme labor, back off from it to recover, allowing your subconscious mind to process all of it and then enter the fray with newfound vigor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Remo goes on to explain the 5 stages of strategic procrastination:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;1. Have a vision or goal&lt;/strong&gt;. &lt;br&gt;
Start working on them immediately, today, as soon as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Take massive action every single day&lt;/strong&gt; &lt;br&gt;
Move closer constantly. Put in significant amounts of effort and work. You have to become obsessed with your thing if you want extraordinary results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Reach a point of saturation&lt;/strong&gt; &lt;br&gt;
Exert your mental powers and feel as if your mind has been drained like a sponge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Initiate strategic procrastination&lt;/strong&gt;&lt;br&gt;
Back off and focus on recovery. Walk, exercise, play around and relax. Don’t forget about your work entirely but don’t manically focus on it either. Ponder over it quickly but not too hard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Get back to work&lt;/strong&gt; &lt;br&gt;
After proper recollection of resources, you have to start putting in the work again; otherwise, you’re only procrastinating not strategically procrastinating. This part is essential and the one in which you produce your most excellent work. You re-enter the zone with newfound vigor and creative insight so that you could achieve glory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Implementation
&lt;/h2&gt;

&lt;p&gt;Strategic or not, what did this procrastination lead to? What was the ultimate solution to implementing PKCE with a serverless application? &lt;/p&gt;

&lt;h3&gt;
  
  
  Firebase Firestore
&lt;/h3&gt;

&lt;p&gt;Reminding myself of why and how PKCE is used throughout the development of the project helped to clarify the requisites for a secure PKCE implementation. In the simplest terms, I just needed to be able to store a random value for a specific user and then recall that value when they came back to my site. &lt;/p&gt;

&lt;p&gt;I knew that I was already using &lt;a href="https://firebase.google.com/docs/firestore"&gt;Firebase Firestore&lt;/a&gt; for storage so that problem was solved but I wasn’t sure how I could map user sessions together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anonymous Authentication
&lt;/h3&gt;

&lt;p&gt;We can solve the need to map requests to users by using &lt;a href="https://firebase.google.com/docs/auth/web/anonymous-auth"&gt;Firebase Anonymous Authentication&lt;/a&gt;. This creates temporary accounts that are tied to a user's session. Using this authentication, we now have a User ID that we can use in our Firebase Cloud Functions.&lt;/p&gt;

&lt;p&gt;Let’s take a look at the code. Here we have the function responsible for installing the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d0QIhTcL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bg96urvn57od4gobcow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d0QIhTcL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bg96urvn57od4gobcow.png" alt="Install Function" width="853" height="840"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On line 72 you can see that we immediately have access to the context.auth.uid variable. This is thanks to enabling anonymous authentication. We use the &lt;code&gt;uid&lt;/code&gt; along with a random value in our &lt;code&gt;state&lt;/code&gt; to ensure that the state is unique for each request while also passing the &lt;code&gt;uid&lt;/code&gt; to the redirect URL.&lt;/p&gt;

&lt;p&gt;One line 73 we are generating a random Code Verifier for use with PKCE. Looking down at line 98, we can see that we then store this in our Firestore database. We set the ID of the document as the &lt;code&gt;uid&lt;/code&gt; so that we can reference it later and then simply store the &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;verifier&lt;/code&gt; values that we generated.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at the function that serves as our redirect URL for OAuth. This function is responsible for receiving the &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;verifier&lt;/code&gt; information that we set previously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JFcTWfv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dboa5jpzypftzdo8vj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JFcTWfv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dboa5jpzypftzdo8vj4.png" alt="Redirect URL Function" width="880" height="1003"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On line 119 we are parsing out the uid from the state value. Then on line 127 we’re fetching the state and verifier parameters that we stored earlier using that uid value.&lt;/p&gt;

&lt;p&gt;Then on lines 135 - 139, we are validating our parameters. Finally, we use the Zoom OAuth API along with our verifier to get our accessToken and use the Zoom API to deep link our user to our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;Make sure to follow us on dev.to so you can stay updated on our latest blogs. If you haven’t already &lt;a href="https://github.com/zoom/zoomapps-serverless-vuejs"&gt;check out our github&lt;/a&gt;! Get started right away using our sample application so you can build out the next killer Zoom App! &lt;/p&gt;

&lt;p&gt;Also, make sure that you check out &lt;a href="https://dev.to/remojansen/strategic-procrastination-and-software-design-559m"&gt;Strategic Procrastination and Software Design&lt;/a&gt; if your brain works like mine does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank You for Reading!
&lt;/h2&gt;

&lt;p&gt;Thanks for taking the time to read this post. If you have any lingering questions or just want to chat about building the future of collaboration please head over to our &lt;a href="https://devforum.zoom.us/"&gt;Developer Forum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>firebase</category>
      <category>security</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Building Serverless Zoom Apps</title>
      <dc:creator>Max Mansfield</dc:creator>
      <pubDate>Wed, 09 Nov 2022 18:17:28 +0000</pubDate>
      <link>https://dev.to/zoom/building-serverless-zoom-apps-5ef4</link>
      <guid>https://dev.to/zoom/building-serverless-zoom-apps-5ef4</guid>
      <description>&lt;p&gt;When we build Zoom Apps, we’re creating tools that have the potential to be used by millions of people every day to do their jobs. The difficulty here is that we’re writing real-time, collaborative, and distributed apps using monolithic tools that are designed to solve different problems.&lt;/p&gt;

&lt;p&gt;We can deploy a docker image and orchestrate clusters to make sure we have a highly available and scalable application but at the end of the day, we are still responsible for maintaining and updating that server infrastructure to make sure our app continues to work for all users.&lt;/p&gt;

&lt;p&gt;Whether we’re staying late yet again dealing with crashed servers, or deciphering system configuration in an attempt to secure and optimize our app there is a lot to think about for a backend development team.&lt;/p&gt;

&lt;p&gt;Often, we end up working against our tools rather than with them which is ironic when we’re configuring these servers and orchestrating clusters just to reliably run the logic that makes our app awesome.&lt;/p&gt;

&lt;p&gt;Today, let’s talk about improving our developer experience in a production-ready environment way that allows us to experiment, fail fast and win big&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Expect from this guide
&lt;/h2&gt;

&lt;p&gt;I’m hoping you can answer the following questions after this guide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is a “Serverless” App?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How can we make a Zoom App serverless?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is the quickest way to get started?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is a Zoom App?
&lt;/h2&gt;

&lt;p&gt;For readers that are unfamiliar with what exactly a Zoom App is I recommend checking our &lt;a href="https://dev.to/zoom/introducing-zoom-apps-33he"&gt;Introduction to Zoom Apps&lt;/a&gt; series.&lt;/p&gt;

&lt;p&gt;In one sentence, I would say it’s a super-powered web app. Meaning, you’ve got the flexibility of a web app with the reach and in-client features of Zoom right at your fingertips. &lt;/p&gt;

&lt;p&gt;With the Zoom Apps SDK, we can use JavaScript or TypeScript to create first-class applications to enhance the meeting experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the catch?
&lt;/h2&gt;

&lt;p&gt;So we know that Zoom Apps are super-powered web apps which means they have the same considerations as a typical web app. &lt;/p&gt;

&lt;p&gt;This is great for web developers because it means we are working in a familiar landscape but it’s key to understand that we have the same challenges as writing a typical web application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What will our server infrastructure be?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How can we ensure high availability?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cluster Orchestration? Load Balancing? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What about our databases?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list goes on! There’s certainly a lot we need to think about as developers to get started building.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is that a Catch?
&lt;/h2&gt;

&lt;p&gt;it might be easy to think those are the components of a web app. That’s simply the boilerplate which is why I think a lot of developers find the initial setup and configuration of a production-ready project to be one of the biggest barriers to experimenting and failing fast.&lt;/p&gt;

&lt;p&gt;For a lot of developers, I think the problems we like solving are quite a bit more nuanced and we don’t want to maintain what is effectively boilerplate for our app. &lt;/p&gt;

&lt;p&gt;When we look at the server infrastructure including our storage, authentication, user models, and content delivery as part of the boilerplate we can start to see how monolithic tools and technologies break down for us. &lt;/p&gt;

&lt;p&gt;Instead, if we can reuse some of the boilerplate server code that we need and modularize our infrastructure we can provision, develop and deploy applications instantly.&lt;/p&gt;

&lt;p&gt;That’s where serverless apps come in!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes a Serverless App?
&lt;/h2&gt;

&lt;p&gt;Serverless technology is based on a microservice architecture that exposes one or more services to be used as modular units for your application per your use case.&lt;/p&gt;

&lt;p&gt;What does this look like in the real world? It means that you don’t have to think about any of the servers for your apps. Sure there is a computer somewhere that is running your code but the best part about serverless architecture is that you don’t have to factor in the underlying technologies when building out your next killer app.&lt;/p&gt;

&lt;p&gt;Instead, we’ll be using a platform that encompasses the backend and logic of a server that we can easily consume in our front-end application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend as a Service (BaaS)
&lt;/h3&gt;

&lt;p&gt;Not thinking about servers means using a backend as a service where you don’t have to worry about updating your operating system or patching your database. &lt;/p&gt;

&lt;p&gt;Where cloud storage is automatically configured and your frontend code is hosted through a CDN. All of this represents hours and hours of research, setup, testing, and implementation on its own.&lt;/p&gt;

&lt;p&gt;I really can’t overstate how significant of a head start this is on developing an MVP that you would want as your product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions as a Service (FaaS)
&lt;/h3&gt;

&lt;p&gt;While we have the backend systems available as services, we still need a way to implement our custom server logic. &lt;/p&gt;

&lt;p&gt;Luckily serverless architectures provide functions as a service which are short-lived instances that run your backend logic.&lt;/p&gt;

&lt;p&gt;As these instances are so temporary, you’re only charged for exactly what you use and you never have to deal with runtime errors related to out-of-date system dependencies&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros and Cons
&lt;/h2&gt;

&lt;p&gt;As we know, nothing is perfect so let’s take a moment to go over some of the Pros and Cons of serverless applications:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cost Effective&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easily Scalable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero Maintenance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shorter Time-to-Market&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Complex Debugging &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vendor Dependency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-Tenancy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Costly Compute Tasks&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking at the pros, we’ve covered most of this already as we’ve learned about serverless architecture. We have less to manage, and containerized code with more precise billing. This means less of a headache for us and therefore a shorter, and cheaper, time to market.&lt;/p&gt;

&lt;p&gt;It’s when we look at the cons of serverless applications that we can learn more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Complex Debugging
&lt;/h3&gt;

&lt;p&gt;Since your code is running on another server, debugging can sometimes be time-consuming and complex with server errors on a cloud-based server. With the sample code that we’ll be using in this guide, the use of Local Emulators greatly improves our debugging experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vendor Dependency
&lt;/h3&gt;

&lt;p&gt;As there currently isn’t an ORM of sorts for cloud vendors often writing a serverless application can lock you into a specific vendor. Of course, you can make the migration between services relatively pain-free by wrapping your database calls with your multi-vendor API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Tenancy
&lt;/h3&gt;

&lt;p&gt;This is a new concern for our security engineers out there that are looking to adopt serverless applications. Due to the shared nature of most cloud computing servers, there is a risk that vulnerabilities such as privilege escalation or memory leaks can lead to data breaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Costly Compute Tasks
&lt;/h3&gt;

&lt;p&gt;Running costly compute tasks on a FaaS is inadvisable and instead should only be used for short-lived tasks like a typical server route. Using the ephemeral containers which are charged based on usage time to compute data can not only cost quite a bit but also take too long.&lt;/p&gt;

&lt;p&gt;Instead, the cloud platform likely provides other compute or VPS services that would be more applicable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Firebase
&lt;/h2&gt;

&lt;p&gt;Firebase is a Platform as a Service (PaaS) that provides Cloud Functions and Backend services. It has usable free tiers and intuitive paths to get started quickly. &lt;/p&gt;

&lt;p&gt;These techniques and tips apply to any Paas/IaaS provider through the steps to implement will vary.&lt;/p&gt;

&lt;p&gt;Throughout this guide, we will use three functions of firebase&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Functions
&lt;/h3&gt;

&lt;p&gt;These fulfill the FaaS requirement for our serverless application quite well. As described by Firebase these will allow us to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Automatically run backend code in response to events triggered by Firebase features and HTTPS requests&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Firestore
&lt;/h3&gt;

&lt;p&gt;This will allow us to sync data between our various clients without having to put any thought into database configuration. Just make a schema for the shape of our database and push data!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Flexible, scalable NoSQL cloud database to store and sync data for client and server-side development&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Hosting
&lt;/h3&gt;

&lt;p&gt;This is how we will serve content to our users. We can set it up as a dynamic or static host and either way it will automatically be configured to scale and distribute our content globally.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With a single command, you can quickly deploy web apps and serve both static and dynamic content to a global CDN&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Replacing our Server
&lt;/h2&gt;

&lt;p&gt;As some of you may know, we have a Basic Sample Zoom App that uses a simple express server to demonstrate the bare minimum needed to get started with a Zoom App.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j4uCP6B6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rs3jkresc1b3gwaft0hj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j4uCP6B6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rs3jkresc1b3gwaft0hj.png" alt="Zoom Github" width="880" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Being a basic server, it’s still responsible for quite a bit! Let’s take a look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zoom Apps Authorization Flow
&lt;/h3&gt;

&lt;p&gt;Our server is currently responsible for acting as the redirect URL for our Zoom App which can receive the access token. This is something we specifically need a server for because we can’t expose the token to a web client.&lt;/p&gt;

&lt;p&gt;This is where Cloud Functions come in. Cloud Functions allow us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Receive the Authorization Code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Obtain the Access Token&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make Requests to the Zoom API&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and so much more!&lt;/p&gt;

&lt;h3&gt;
  
  
  OWASP Headers
&lt;/h3&gt;

&lt;p&gt;If you’re already a Zoom App Developer you know that the OWASP security headers are essential for getting your app up and running. Without them, you’ll see what I call the white screen of death - a blank zoom app with only a console error to guide you.&lt;/p&gt;

&lt;p&gt;When we’re working with the sample code today, we can set production headers in firebase.json and use the development server configuration to set the development headers.&lt;/p&gt;

&lt;p&gt;Luckily, if you clone the code you’ll see that this is already done for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zoom Apps Context Header
&lt;/h3&gt;

&lt;p&gt;If you have looked at any of our Zoom Apps sample applications so far, you’ll notice that they decrypt and unpack the Zoom Apps Header that is sent by the Zoom client.&lt;/p&gt;

&lt;p&gt;When we don’t have direct access to a server, and in this case, we are using a Single Page Application, then how can we read the request headers?&lt;/p&gt;

&lt;p&gt;The answer is that we don’t. We can get all the information we need from the Zoom Apps JS SDK. While we could set a cloud function as our homepage to decipher the headers this is impractical when we have the Zoom Apps SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client Side Routing
&lt;/h3&gt;

&lt;p&gt;For readers that haven’t used client-side routing before, it is incredible! Instead of making requests to the server, we can use JavaScript bundles and instantly load the new chunk of code. &lt;/p&gt;

&lt;p&gt;This means fewer requests to your server, less bandwidth, and instant load times.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Look at the Demo App
&lt;/h2&gt;

&lt;p&gt;Our sample today can be found on our GitHub and is a serverless, single-page, todo application. Yes, it uses all the buzzwords and is built on a modern tech stack around an intuitive developer experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jIQ5Nd8H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7h493489ywa3n13jdod1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jIQ5Nd8H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7h493489ywa3n13jdod1.png" alt="Sample Serverless App" width="880" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zoom/zoomapps-serverless-vuejs"&gt;Clone The Repo Here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Firebase
&lt;/h2&gt;

&lt;p&gt;This step should be very simple which is one of the reasons I built this sample around Firebase. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Join a Free Account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a New Project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable Hosting, Functions &amp;amp; Firestore&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set Up Secrets Manager&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Firebase Development
&lt;/h2&gt;

&lt;p&gt;When working with Firebase, you’ll want to make use of the Local Emulators.&lt;/p&gt;

&lt;p&gt;What are Local Emulators? They are local services that emulate the serverless architecture on your local system. This allows you to test and debug locally which offers instant access to more detailed debug logs&lt;/p&gt;

&lt;p&gt;Likewise, you’re able to make changes to your application locally and retain hot reloading which drastically improves productivity&lt;/p&gt;

&lt;p&gt;Once we have the emulators running, we can proxy the function emulators using our development server so that our OAuth Redirect URL can be used. This is all set up in the sample application that we have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure your Zoom App
&lt;/h2&gt;

&lt;p&gt;When working with a development environment, we have a .secrets.local file for our Zoom App credentials. However, when we are running in a production environment, we are lucky enough to have a Secrets Manager to create, rotate and manage application secrets.&lt;/p&gt;

&lt;p&gt;In both cases, the secrets will be automatically injected into our application environment.&lt;/p&gt;

&lt;p&gt;In the image below, you can see that for development we are using a tunnel to our local system for our development credentials (&lt;a href="https://ngrok.com"&gt;Ngrok&lt;/a&gt; in this case). Notice the format of the redirect URL matches the path to a local emulator.&lt;/p&gt;

&lt;p&gt;For production environments, we are using the actual hosting URL and cloud function URL provided by Firebase. This enables a smooth developer experience with a logical separation of environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;If you haven’t already &lt;a href="https://github.com/zoom/zoomapps-serverless-vuejs"&gt;check out our github&lt;/a&gt;! Get started right away using our sample application so you can build out the next killer Zoom App! &lt;/p&gt;

&lt;p&gt;If you’re feeling comfortable with Cloud Functions and Zoom Apps take a look at the next post in this series - &lt;a href="https://dev.to/zoom/what-i-learned-implementing-pkce-for-serverless-zoom-apps-1k9l"&gt;What I Learned Implementing PKCE for Serverless Zoom Apps&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank You for Reading!
&lt;/h2&gt;

&lt;p&gt;Thanks for taking the time to read this guide. If you have any lingering questions or just want to chat about building the future of collaboration please head over to our &lt;a href="https://devforum.zoom.us/"&gt;Developer Forum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>javascript</category>
      <category>vue</category>
      <category>serverless</category>
    </item>
    <item>
      <title>How to Setup the Basic Zoom App Sample</title>
      <dc:creator>Max Mansfield</dc:creator>
      <pubDate>Tue, 21 Jun 2022 16:01:46 +0000</pubDate>
      <link>https://dev.to/zoom/how-to-setup-the-basic-zoom-app-sample-bp1</link>
      <guid>https://dev.to/zoom/how-to-setup-the-basic-zoom-app-sample-bp1</guid>
      <description>&lt;p&gt;Welcome to part 3 of our Getting Started with Zoom Apps series! Part one of our series covered an overview of Zoom Apps, and in part two, we even created one. This section will look at setting up and running our sample Hello World Zoom App.&lt;/p&gt;

&lt;p&gt;If you're following along, you should have the Client ID and Client Secret from your Zoom App and an OAuth Redirect URL from a running Ngrok tunnel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Node.JS (NPM)&lt;/li&gt;
&lt;li&gt;  A Zoom App on the Zoom Marketplace&lt;/li&gt;
&lt;li&gt;  Client ID and Client Secret&lt;/li&gt;
&lt;li&gt;  Redirect URL&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About the App
&lt;/h2&gt;

&lt;p&gt;The sample Zoom App code we will be running today uses vanilla JavaScript and Express to demonstrate the bare minimum code needed to get up and running while still following best practices.&lt;/p&gt;

&lt;p&gt;On that note, this app doesn't really do much. It's a template for other sample applications and is designed to be extensible. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setup and Install
&lt;/h2&gt;

&lt;p&gt;Now we're going to set up the code needed to run the app and all the dependencies. First, clone the git repository found here: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zoom/zoomapps-sample-js" rel="noopener noreferrer"&gt;https://github.com/zoom/zoomapps-sample-js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use NPM to install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add Credentials
&lt;/h2&gt;

&lt;p&gt;Installing dependencies creates the .env file that holds our application secrets while developing in a secure environment. &lt;/p&gt;

&lt;p&gt;Open the .env file and follow the instructions to fill out the fields. The SESSION_SECRET field will already have a random value generated for development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Client ID for your Zoom App
ZM_CLIENT_ID=

# Client Secret for your Zoom app
ZM_CLIENT_SECRET=

# Redirect URI set for your app in the Zoom Marketplace
ZM_REDIRECT_URL=

# Sign Session Cookies
SESSION_SECRET=3e571b471f611f7cae69cadcaa786e82a93609ffdcfe9bab93bf52f356a4d9ae
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Start the App
&lt;/h2&gt;

&lt;p&gt;Run the app in development mode to use the credentials from the .env file and watch for changes to files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts our app on port 3000 by default, but you can set the PORT environment variable to change that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9ny0ivlqq5ywuteajh2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9ny0ivlqq5ywuteajh2.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Using the App
&lt;/h1&gt;

&lt;p&gt;Navigate to your Ngrok URL in your browser to display your Zoom App home page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjtbjvg2ig32kw50kj6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjtbjvg2ig32kw50kj6d.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Our Zoom App knows that we're running it from the browser and gives us the option to install the app. &lt;/p&gt;

&lt;p&gt;Click the install link and follow the prompts to authorize the app. If you authorized your app when creating it, then this will open your app in the Zoom Client:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffm7n9bzlkxkl8iax08a0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffm7n9bzlkxkl8iax08a0.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, you can see our Zoom App is running directly from Zoom!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97fslodwgs8l98chol3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97fslodwgs8l98chol3o.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Great job! You've created, installed, and run your Zoom App. Feel free to take a look at the code, and please see our next section for information on how you can continue your journey as a Zoom App Developer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Continue Learning
&lt;/h1&gt;

&lt;p&gt;Thank you for reading through this three-part series introducing Zoom Apps! I hope this series has been helpful and you're inspired to create something awesome with all the tools that Zoom Apps provides. &lt;/p&gt;

&lt;p&gt;I've included links to our documentation and further resources on learning about Zoom. Happy Coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.zoom.us/docs/zoom-apps/introduction" rel="noopener noreferrer"&gt;Overview&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.zoom.us/docs/zoom-apps/getstarted" rel="noopener noreferrer"&gt;Create An App&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.zoom.us/docs/zoom-apps/referenceapp" rel="noopener noreferrer"&gt;Quickstart&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.zoom.us/docs/zoom-apps/guides/layers-api" rel="noopener noreferrer"&gt;Immersive Mode&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.zoom.us/docs/zoom-apps/guides/collaboration-mode" rel="noopener noreferrer"&gt;Collaborate Mode&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Video Guides
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://youtu.be/otlyDxnU-RI" rel="noopener noreferrer"&gt;How To Create a Zoom App&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=SS87nqO9ScQ" rel="noopener noreferrer"&gt;How To Configure the Basic Zoom App Sample&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sample Apps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zoom/zoomapps-advancedsample-react" rel="noopener noreferrer"&gt;Advanced React Sample&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zoom/zoomapps-sample-js" rel="noopener noreferrer"&gt;Hello World Sample&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zoom/zoomapps-customlayout-js" rel="noopener noreferrer"&gt;Immersive Mode Sample&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zoom/zoomapps-texteditor-vuejs" rel="noopener noreferrer"&gt;Collaborative Mode Sample&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Setting Up Your Zoom App</title>
      <dc:creator>Max Mansfield</dc:creator>
      <pubDate>Tue, 21 Jun 2022 16:01:26 +0000</pubDate>
      <link>https://dev.to/zoom/setting-up-your-zoom-app-4h35</link>
      <guid>https://dev.to/zoom/setting-up-your-zoom-app-4h35</guid>
      <description>&lt;p&gt;Thanks for joining us again for part two of our three-part series on Zoom Apps. If you missed it, the last section introduced what Zoom Apps are and what they can do. In this section, we'll go over how we can create a Zoom App and how we can best use our granular permissions system.&lt;/p&gt;

&lt;p&gt;Before we get started, you'll need a Zoom user account with permission to create a Zoom App. If you're the account admin, you're all set. If you're unsure what your role is, you can check the support article &lt;a href="https://support.zoom.us/hc/en-us/articles/201363173-Zoom-user-types-roles" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ngrok&lt;/li&gt;
&lt;li&gt;A Zoom account&lt;/li&gt;
&lt;li&gt;A Zoom user that has Zoom App Developer permissions in their role&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Ngrok
&lt;/h2&gt;

&lt;p&gt;If you want to follow along with configuring your app and setting up our sample Zoom App, you'll need Ngrok or another local tunneling tool.&lt;/p&gt;

&lt;p&gt;Start a Ngrok tunnel and leave it open while testing the sample app:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ ngrok http 3000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save the HTTPS forwarding URL that you see for later and leave Ngrok running. We'll refer to this URL as &lt;a href="https://example.ngrok.io" rel="noopener noreferrer"&gt;https://example.ngrok.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszuqpvro7ezi728i6d87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszuqpvro7ezi728i6d87.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Note, unless you're using a paid Ngrok plan, Ngrok will regenerate a new URL each time you restart, so we'll only want to use this for quick testing purposes.&lt;/p&gt;

&lt;p&gt;Ngrok can also impact the latency and bandwidth of the network connection, so you shouldn't use it for performance or latency testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a New Zoom App
&lt;/h2&gt;

&lt;p&gt;Now that you're settled and logged in to your Zoom account, head over to the &lt;a href="https://marketplace.zoom.us" rel="noopener noreferrer"&gt;Zoom App Marketplace&lt;/a&gt; at &lt;a href="https://marketplace.zoom.us" rel="noopener noreferrer"&gt;https://marketplace.zoom.us&lt;/a&gt; to start.&lt;/p&gt;

&lt;p&gt;Click the dropdown that says Develop and then click Build App:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqscmo9xy61aodrnasaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqscmo9xy61aodrnasaz.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;You should see a few App types listed on the next page. Click Create under the tile that says Zoom Apps. In the dialog that appears, fill out the initial information:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9yd4aneh3az4irb7g6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9yd4aneh3az4irb7g6k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  App Name
&lt;/h3&gt;

&lt;p&gt;As you may have guessed, this is your app's name. Choose wisely, as you can't change the app's name from now on, and this will be the app's name if published to the Zoom App Marketplace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose app type
&lt;/h3&gt;

&lt;p&gt;At the time of writing, only user-managed apps are available to create. With user-managed apps, each user will install and authorize the app individually. The access token has data access scoped only to the authorized user.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distribution
&lt;/h3&gt;

&lt;p&gt;Leave this option checked if you plan to list your app on the Zoom App Marketplace so that anyone with a Zoom account can install it.&lt;/p&gt;

&lt;p&gt;After you click Create, a new Zoom App is created and will be ready to configure. &lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Your App
&lt;/h2&gt;

&lt;p&gt;Now that you've created your app, you should see a page similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rndcs1jddrc57udgbu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rndcs1jddrc57udgbu4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's review some essential tabs we can use to configure our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  App Credentials
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Home URL
&lt;/h3&gt;

&lt;p&gt;This is the landing page for your Zoom App and the URL that Zoom will display when a user opens your app. To run the Sample App, enter your Ngrok URL here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client ID and Client Secret
&lt;/h3&gt;

&lt;p&gt;The Client ID and Secret are similar to a username and password of an app. In that sense, you'll always want to securely store your credentials and never share them or commit them to your repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redirect URL for OAuth
&lt;/h3&gt;

&lt;p&gt;The OAuth Redirect URL is the URL to which the OAuth flow will redirect once the user has authorized your app. Make sure you add this URL to the OAuth allow list and the Domain Allow List below.&lt;/p&gt;

&lt;p&gt;To set this up with our sample app, enter your Ngrok URL with the /auth route appended:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://example.ngrok.io/auth" rel="noopener noreferrer"&gt;https://example.ngrok.io/auth&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OAuth Allow List
&lt;/h3&gt;

&lt;p&gt;These are the domains the app can use for OAuth redirects, so make sure to add the Redirect URL from above here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Allow List
&lt;/h3&gt;

&lt;p&gt;First, we'll want to add the domain for our OAuth Redirect URL and Home page here. This is the domain from our Ngrok URL.&lt;/p&gt;

&lt;p&gt;The Sample Apps also use our CDN for the SDK to make sure you add the domain for that CDN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;appssdk.zoom.us
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, if we connect to any domains from our app, we'll want to add them here too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Information
&lt;/h2&gt;

&lt;p&gt;Make sure to fill out the information tab with details relevant to your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2qfrpfz7emuo4xebs92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2qfrpfz7emuo4xebs92.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;Now that we have our credentials and our app connects to our domain (our Ngrok URL), we are ready for the fun part.&lt;/p&gt;

&lt;p&gt;When we navigate to the Features Tab, we can see a lot of different functions and capabilities we can enable for our Zoom App to use.&lt;/p&gt;

&lt;p&gt;Access to a feature or function will need to be enabled here for your app to use. Here is where you'll enable APIs or features like Guest Mode or Collaborate Mode. Note: If you add new features to an existing app, they can be used by reinstalling your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzl2k99mva9lhlkjya6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzl2k99mva9lhlkjya6m.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To set up our Hello World app, we need to click Add APIs under the Zoom App SDK section and select the shareApp API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjc2xernpu2vlhe5t3h4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjc2xernpu2vlhe5t3h4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scopes
&lt;/h2&gt;

&lt;p&gt;Moving on to the scopes tab, we can see that we can add OAuth scopes which define the data our credentials can access. Since we're just setting up a simple app today, select the zoomapp:inmeeting scope and click continue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldu1a47ygcqzc6a71va9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldu1a47ygcqzc6a71va9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Your App
&lt;/h2&gt;

&lt;p&gt;Navigate to the Activation tab and click the Add button to install your app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pia6g9m3wdw00i6ftk7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pia6g9m3wdw00i6ftk7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎉 Congratulations! 🎉 You've just created your very own Zoom App.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run Your App
&lt;/h2&gt;

&lt;p&gt;Now that we have our credentials and installed our app, we're ready to set up our Hello World Zoom App and run it from the Zoom Client.&lt;/p&gt;

&lt;p&gt;Join us in part three of this series, where we'll use our credentials and Ngrok URL to open our app.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Introducing Zoom Apps</title>
      <dc:creator>Max Mansfield</dc:creator>
      <pubDate>Tue, 21 Jun 2022 16:01:12 +0000</pubDate>
      <link>https://dev.to/zoom/introducing-zoom-apps-33he</link>
      <guid>https://dev.to/zoom/introducing-zoom-apps-33he</guid>
      <description>&lt;p&gt;Zoom Apps allow you to bring your web applications front and center within Zoom Meetings and Webinars. They integrate seamlessly with Zoom using a lightweight and framework agnostic JavaScript SDK that enables you to provide a unique experience to participants and hosts of your meetings. &lt;/p&gt;

&lt;p&gt;With a broad feature-set to customize the meeting experience, it's simple to build the next must-have meeting app using familiar tools and web technologies or bring over your existing killer app.&lt;/p&gt;

&lt;p&gt;What's more? Getting started with Zoom Apps couldn't be quicker! Just create an app on our App Marketplace and spin up one of our sample applications to have the power of Zoom at your fingertips.&lt;/p&gt;

&lt;p&gt;Throughout this three-part series, we'll take an in-depth look at what Zoom Apps are, how to configure an app on our App Marketplace and how you can get started running a Hello World Zoom App right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;Zoom Apps are web apps with added APIs and features from the Zoom desktop and mobile clients. Building Zoom Apps gives you the wide-ranging functionality of a web app and the ability to tailor the experience to match your app's best in-meeting and post-meeting UX. Zoom Apps can be installed directly from the Zoom client or &lt;a href="https://marketplace.zoom.us"&gt;Zoom App Marketplace&lt;/a&gt; and will open your web app as a view embedded within the Zoom Client. &lt;/p&gt;

&lt;p&gt;Using granularly scoped OAuth mechanisms and a lightweight JavaScript SDK, we can bring opportunities for new use cases and enhanced meeting experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can Zoom Apps do?
&lt;/h2&gt;

&lt;p&gt;Your web app will display by default as a panel on the side of a meeting, but you can also change this view in various ways based on your app's context. We can expand or pop out this view, fill the entire meeting space, and dynamically customize the experience for each user using features like &lt;a href="https://marketplace.zoom.us/docs/beta-docs/zoom-apps/guides/collaboration-mode"&gt;Collaborate Mode&lt;/a&gt; or our &lt;a href="https://marketplace.zoom.us/docs/beta-docs/zoom-apps/guides/layers-api"&gt;Layers API&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meeting Bots
&lt;/h3&gt;

&lt;p&gt;Let your app interact with users and join the meeting as a helping hand with our new &lt;a href="https://marketplace.zoom.us/docs/zoom-apps/guides/sdk-media-streams"&gt;Meeting Bot&lt;/a&gt; feature powered by Zoom Apps and the &lt;a href="https://marketplace.zoom.us/docs/sdk/native-sdks/introduction"&gt;Zoom Meeting SDK&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collaborate Mode
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://marketplace.zoom.us/docs/zoom-apps/guides/collaboration-mode"&gt;Collaborate Mode&lt;/a&gt; shares a collaborative app and offers a frictionless method for everyone to join in on our favorite collaborative team tools. &lt;/p&gt;

&lt;h3&gt;
  
  
  Immersive Mode
&lt;/h3&gt;

&lt;p&gt;Our &lt;a href="https://marketplace.zoom.us/docs/zoom-apps/guides/layers-api"&gt;Layers API&lt;/a&gt; enables a new immersive opportunity for apps using Zoom's powerful layering system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manage Breakout Rooms
&lt;/h3&gt;

&lt;p&gt;Split the meeting into smaller sessions to enable a customized collaboration and networking flow using our &lt;a href="https://marketplace.zoom.us/docs/zoom-apps/guides/zoom-apps-for-breakout-rooms"&gt;Breakout Rooms API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready? Set. Zoom!
&lt;/h2&gt;

&lt;p&gt;Now that we know what Zoom Apps are let's create our credentials for the app and test out one of the sample applications available to us.&lt;/p&gt;

&lt;p&gt;In the next part of this series, we'll look at creating and configuring your application on the &lt;a href="https://marketplace.zoom.us"&gt;Zoom Marketplace&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
