-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
18 changed files
with
1,445 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.next | ||
|
||
# testing | ||
/coverage | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
.idea | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env | ||
dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## Submission to Miro Marketplace | ||
|
||
Congrats! You have finished building your app & you'd like to publish it for | ||
users. You can submit your app to the | ||
[Miro Marketplace](https://developers.miro.com/docs/submit-your-app) for review. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# 3rd Party OAuth Login (Slack example) | ||
|
||
This app allows you to login to a 3rd party service using OAuth (you will need to provide an OAuth URL). The app tracks if the user has logged in or not via [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). | ||
|
||
# 👨🏻💻 App Demo 🔊(Sound On)🔊 | ||
|
||
https://github.com/miroapp/app-examples/assets/10428517/fef43c9f-d528-4787-8c66-c94e0f88a03d | ||
|
||
# 📒 Table of Contents | ||
|
||
- [Included Features](#features) | ||
- [Tools and Technologies](#tools) | ||
- [Prerequisites](#prerequisites) | ||
- [Run the app locally](#run) | ||
- [Folder Structure](#folder) | ||
- [Contributing](#contributing) | ||
- [License](#license) | ||
|
||
# ⚙️ Included Features <a name="features"></a> | ||
|
||
- [Miro Web SDK](https://developers.miro.com/docs/web-sdk-reference) | ||
- [miro.board.ui.openPanel(options)](https://developers.miro.com/docs/ui_boardui#openpanel) | ||
|
||
# 🛠️ Tools and Technologies <a name="tools"></a> | ||
|
||
- [Express](https://expressjs.com/) | ||
- [Node.js](https://nodejs.org/en) | ||
- [Vite](https://vitejs.dev/) | ||
- [ngrok](https://ngrok.com/) | ||
|
||
# ✅ Prerequisites <a name="prerequisites"></a> | ||
|
||
- You have a [Miro account](https://miro.com/signup/). | ||
- You're [signed in to Miro](https://miro.com/login/). | ||
- Your Miro account has a [Developer team](https://developers.miro.com/docs/create-a-developer-team). | ||
- Your development environment includes [Node.js 14.13](https://nodejs.org/en/download) or a later version. | ||
- All examples use `npm` as a package manager and `npx` as a package runner. | ||
|
||
# 🏃🏽♂️ Run the app locally <a name="run"></a> | ||
|
||
1. Run `npm install` to install dependencies. | ||
2. Run `npm run start` to start the front end. We have a separate server for the backend. \ | ||
Your URL should be similar to this example: | ||
``` | ||
http://localhost:3000 | ||
``` | ||
3. Run `cd src/backend`. | ||
4. Run `npm install`. | ||
5. Run `node app.js`. | ||
6. If you need to use something like ngrok for your redirectURL (I had to do this to go through the OAuth process for my Slack app) run `ngrok http 4000`. | ||
7. Your ngrok forwarding address should look something like: `https://bced-81-59-0-206.ngrok-free.app`. Then your <b>redirect URL</b> in the other service (for me it was in the App Settings in Slack) should be: | ||
`https://bced-81-59-0-206.ngrok-free.app/redirect` | ||
8. Go into `src/backend` and fill in the `.sample.env` file with your OAuthURL, clientId, and clientSecret and rename it to `.env` and then save the file. | ||
|
||
> For me, I had to go into my Slack App settings -> Basic Settings for the clientId and ClientSecret. I had to go to App Settings -> Manage Distribution and then check all the boxes, and then I was able to find the "Sharable URL" that I used as my "redirectURL". Also this likely requires the app to have some scopes, so you would have to add that in the OAuth and permission page of the app settings. | ||
9. Open the [app manifest editor](https://developers.miro.com/docs/manually-create-an-app#step-2-configure-your-app-in-miro) by clicking **Edit in Manifest**. \ | ||
In the app manifest editor, configure the app as follows, and then click save: | ||
|
||
```yaml | ||
# See https://developers.miro.com/docs/app-manifest on how to use this | ||
appName: 3rd Party Oauth Login | ||
sdkVersion: SDK_V2 | ||
sdkUri: http://localhost:3000 | ||
scopes: | ||
- boards:read | ||
- boards:write | ||
``` | ||
10. Go back to your app home page, and under the `Permissions` section, you will see a blue button that says `Install app and get OAuth token`. Click that button. Then click on `Add` as shown in the video below. <b>In the video we install a different app, but the process is the same regardless of the app.</b> | ||
|
||
> ⚠️ We recommend to install your app on a [developer team](https://developers.miro.com/docs/create-a-developer-team) while you are developing or testing apps.⚠️ | ||
|
||
https://github.com/miroapp/app-examples/assets/10428517/1e6862de-8617-46ef-b265-97ff1cbfe8bf | ||
|
||
11. Go to your developer team, and open your boards. | ||
12. Click on the plus icon from the bottom section of your left sidebar. If you hover over it, it will say `More apps`. | ||
13. Search for your app `3rd Party OAuth Login` or whatever you chose to name it. Click on your app to use it, as shown in the video below. <b>In the video we search for a different app, but the process is the same regardless of the app.</b> | ||
|
||
https://github.com/horeaporutiu/app-examples-template/assets/10428517/b23d9c4c-e785-43f9-a72e-fa5d82c7b019 | ||
|
||
# 🗂️ Folder structure <a name="folder"></a> | ||
|
||
``` | ||
. | ||
├── src <-- main logic for the app | ||
│ └── app.js <-- handles the button clicks and front end interaction | ||
│ └── index.js <-- handles clicking on app icon in Miro | ||
│ └── style.css <-- CSS styles for the app. | ||
│ └── backend <-- The node.js express backend | ||
│ └── app.js <-- handles redirect and also passes OAuth URL to front end | ||
│ └── .sample.env <-- Env variable for your OAuth URL. rename it to .env | ||
└── index.html <-- The app entry point. | ||
└── app.html <-- The app entry point. | ||
``` | ||
# 🫱🏻🫲🏽 Contributing <a name="contributing"></a> | ||
If you want to contribute to this example, or any other Miro Open Source project, please review [Miro's contributing guide](https://github.com/miroapp/app-examples/blob/main/CONTRIBUTING.md). | ||
# 🪪 License <a name="license"></a> | ||
[MIT License](https://github.com/miroapp/app-examples/blob/main/LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# See https://developers.miro.com/docs/app-manifest on how to use this | ||
appName: 3rd Party Oauth Login | ||
sdkUri: "http://localhost:3000" | ||
scopes: | ||
- boards:read | ||
- boards:write |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<script src="https://miro.com/app/static/sdk/v2/miro.js"></script> | ||
<title>3rd Party Oauth Login</title> | ||
</head> | ||
<body> | ||
<div id="root"> | ||
<div class="grid wrapper"> | ||
<div class="cs1 ce12"> | ||
<img src="/src/assets/congratulations.png" alt="" /> | ||
</div> | ||
<div class="cs1 ce12"> | ||
<p> | ||
You're about to learn how to go through OAuth of a 3rd party tool | ||
and then return back as a logged in user. You'll need | ||
<b>an app in a 3rd party tool</b> (outside of Miro), with the | ||
following: | ||
</p> | ||
<ul> | ||
<li><b>clientID</b></li> | ||
<li><b>clientSecret</b></li> | ||
<li><b>OAuth URL</b></li> | ||
</ul> | ||
</div> | ||
<div id="loginText" class="cs1 ce12"> | ||
<h1>Click below to login!</h1> | ||
</div> | ||
<div id="textHeaderPanel" class="cs1 ce12"> | ||
<a id="loginButton" class="button button-primary" target="_blank"> | ||
Login to 3rd party tool | ||
</a> | ||
</div> | ||
<div id="statusContainer" class="cs1 ce12"> | ||
<h1>User Login Status</h1> | ||
<p id="loginStatus"></p> | ||
</div> | ||
<a id="logoutButton" class="button button-primary" target="_blank"> | ||
Logout from 3rd party tool | ||
</a> | ||
</div> | ||
</div> | ||
|
||
<script type="module" src="/src/app.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<link rel="stylesheet" href="/src/assets/style.css" /> | ||
<script src="https://miro.com/app/static/sdk/v2/miro.js"></script> | ||
<title>3rd Party Oauth Login</title> | ||
</head> | ||
<body> | ||
<div id="root"> | ||
<div class="grid container"> | ||
<div class="cs1 ce12"> | ||
<img src="/src/assets/welcome.png" alt="" /> | ||
</div> | ||
<div class="cs1 ce12"> | ||
<h1>Great, your app is running locally</h1> | ||
<p> | ||
You can now create your Developer team to get your app running in | ||
Miro. | ||
</p> | ||
</div> | ||
<div class="cs1 ce12"> | ||
<a | ||
class="button button-primary" | ||
href="https://developers.miro.com/docs/create-a-developer-team" | ||
target="_blank" | ||
> | ||
Create a Developer team | ||
</a> | ||
</div> | ||
<div class="cs1 ce12"> | ||
<p> | ||
To see your app, open it in a app panel on Miro.com, or preview it | ||
at <a href="/app.html" class="link link-primary">this url</a> | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
<script type="module" src="/src/index.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"compilerOptions": { | ||
"typeRoots": ["./node_modules/@types", "./node_modules/@mirohq"] | ||
}, | ||
"include": ["src"], | ||
"exclude": ["node_modules"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "3rd-party-oauth-login", | ||
"version": "0.1.0", | ||
"license": "MIT", | ||
"scripts": { | ||
"start": "vite", | ||
"build": "vite build", | ||
"serve": "vite preview" | ||
}, | ||
"dependencies": { | ||
"mirotone": "5" | ||
}, | ||
"devDependencies": { | ||
"vite": "3.0.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* eslint-disable no-undef */ | ||
// check eslint global config | ||
import "./assets/style.css"; | ||
|
||
const loginBtn = document.getElementById("loginButton"); | ||
const logoutBtn = document.getElementById("logoutButton"); | ||
const loginText = document.getElementById("loginText"); | ||
|
||
// Attach click event listeners | ||
loginBtn.addEventListener("click", startOAuthFlow); | ||
logoutBtn.addEventListener("click", handleLogout); | ||
|
||
// Add an event listener to the DOMContentLoaded event | ||
document.addEventListener("DOMContentLoaded", function () { | ||
// Call the initialize function when the DOM content is loaded | ||
initialize(); | ||
}); | ||
|
||
// Define a function containing the code you want to run each time index.html is opened | ||
async function initialize() { | ||
logoutBtn.style.display = "none"; | ||
await isLoggedIn(); | ||
} | ||
|
||
// This function displays the user login status on the UI | ||
async function displayLoginStatus(loggedIn) { | ||
try { | ||
const statusParagraph = document.getElementById("loginStatus"); | ||
|
||
if (loggedIn) { | ||
statusParagraph.textContent = | ||
"✅ User is logged in. " + | ||
"🔄 If you want to run this flow again, use the logout button."; | ||
|
||
// Hide the login button and show the logout button | ||
loginBtn.style.display = "none"; | ||
loginText.style.display = "none"; | ||
logoutBtn.style.display = "block"; | ||
} else { | ||
statusParagraph.textContent = "❌ User is not logged in ❌"; | ||
loginBtn.style.display = "block"; | ||
} | ||
return; | ||
} catch (error) { | ||
console.log(error); | ||
} | ||
} | ||
|
||
// This function checks the local storage for the user's id. Local storage is just for demo purposes. | ||
// It is recommended to implement your own storage for a production application. | ||
async function isLoggedIn() { | ||
try { | ||
// Check if the user is logged in by checking the local storage on the browser | ||
const loggedIn = localStorage.getItem("isLoggedIn") === "true"; | ||
|
||
// Check if the currentId exists in the loggedInUserIds array | ||
await displayLoginStatus(loggedIn); | ||
return; | ||
} catch (error) { | ||
console.error("Error fetching or parsing JSON file:", error); | ||
return false; // Handle errors gracefully | ||
} | ||
} | ||
|
||
//this function opens a new browser tab to start the OAuth process | ||
//we then add an event listener to the window to listen for the message from the backend for once the OAuth flow is completed | ||
async function startOAuthFlow() { | ||
try { | ||
const response = await fetch("http://localhost:4000"); | ||
const OAuthURL = await response.json(); | ||
window.open(OAuthURL, "_blank"); | ||
|
||
// Add an event listener to receive messages from the backend, it will be called after the OAuth flow is completed | ||
window.addEventListener("message", async function (event) { | ||
const redirectSuccess = event.data.redirectSuccess; | ||
if (typeof redirectSuccess === "undefined") { | ||
return; | ||
} else if (redirectSuccess) { | ||
this.localStorage.isLoggedIn = true; | ||
await isLoggedIn(); | ||
} else { | ||
console.log("Redirect failed"); | ||
return; | ||
} | ||
}); | ||
} catch (error) { | ||
console.error("Error fetching data:", error); | ||
} | ||
} | ||
|
||
// Handle the logout by clearing the local storage and updating the UI to display the login button | ||
async function handleLogout() { | ||
try { | ||
await localStorage.clear(); | ||
logoutBtn.style.display = "none"; | ||
await displayLoginStatus(false); | ||
return; | ||
} catch (error) { | ||
console.error("Error fetching data:", error); | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
@import "mirotone/dist/styles.css"; | ||
|
||
*, | ||
*:before, | ||
*:after { | ||
box-sizing: border-box; | ||
} | ||
|
||
body { | ||
display: flex; | ||
} | ||
|
||
#root { | ||
width: 100%; | ||
overflow: auto; | ||
padding: var(--space-medium); | ||
} | ||
|
||
img { | ||
max-width: 100%; | ||
height: auto; | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
OAuthURL=https://slack.com/oauth/v2/authorize?client_id=81938855590.6792758974006&scope=chat:write&user_scope=' | ||
clientSecret='' | ||
clientId='' |
Oops, something went wrong.