
Research
Security News
Malicious PyPI Package Exploits Deezer API for Coordinated Music Piracy
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
@mirohq/miro-node
Advanced tools
Reference documentation: https://miroapp.github.io/api-clients/classes/index.Miro.html
Miro class is a wrapper that handles authorization and per-user access token management.
To start using the client create a new instance:
import {Miro} from '@mirohq/miro-node'
const miro = new Miro()
By default client will load the app configuration from environment variables: MIRO_CLIENT_ID
, MIRO_CLIENT_SECRET
, MIRO_REDIRECT_URL
. They can also be provided by passing the options object to the iconstructor.
const miro = new Miro({
clientId: 'your_app_id',
clientSecret: 'your_app_secret',
redirectUrl: 'https://foo.bar/miro_return_url',
})
Other options are documented in the reference.
The client has all methods that are needed to complete Miro authorization flows and make API calls:
miro.isAuthorized(someUserId)
miro.getAuthUrl()
await miro.exchangeCodeForAccessToken(someUserId, req.query.code)
await miro.as(someUserId).getBoards()
Here is a simple implementation of an App using the fastify framework:
import {Miro} from '@mirohq/miro-node'
import Fastify from 'fastify'
import fastifyCookie from '@fastify/cookie'
const miro = new Miro()
const app = Fastify()
app.register(fastifyCookie)
// Generate user ids for new sessions
app.addHook('preHandler', (request, reply, next) => {
if (!request.cookies.userId) {
const userId = Math.random()
reply.setCookie('userId', userId)
request.cookies.userId = userId
}
next()
})
// Exchange the code for a token in the OAuth2 redirect handler
app.get('/auth/miro/callback', async (req, reply) => {
await miro.exchangeCodeForAccessToken(req.cookies.userId, req.query.code)
reply.redirect('/')
})
app.get('/', async (req, reply) => {
// If user did not authorize the app, then redirect them to auth url
if (!(await miro.isAuthorized(req.cookies.userId))) {
reply.redirect(miro.getAuthUrl())
return
}
// Initialize the API for the current user
const api = miro.as(req.cookies.userId)
// Print the info of the first board
for await (const board of api.getAllBoards()) {
return board
}
})
await app.listen({port: 4000})
Most methods (isAuthorized
, exchangeCodeForAccessToken
, api
) will take userId
as a first paramters. This is the internal ID of the user in your application, usually stored in session. It can be either a string or a number.
Client library requires a persistent storage so that it can store user's access and refresh tokens. By default it uses filesystem to store this state. For production deployments we recommend using a custom implementation backed by a database. It is passed as an option to Miro contructor:
const miro = new Miro({
storage: new CustomMiroStorage(),
})
Storage should implement the following interface:
export interface Storage {
read(userId: ExternalUserId): Promise<State | undefined>
write(userId: ExternalUserId, state: State): Awaitable<void>
}
The client will automatically refresh access tokens before making API calls if they are going to expire soon.
.as(userId: string)
method returns an instance of the Api
class. This instance provides methods to create and get Board
models which has methods to create and get Item
model and so forth.
Client provides a few helper methods that make it easy to paginate over all resources. For example getAllBoards method returns an async iterator that can be used to iterate over all available boards:
for await (const board of api.getAllBoards()) {
console.log(board.viewLink)
}
Besides the high level stateful Miro client the library also exposes a stateless low level client:
import {MiroApi} from './index.ts'
const api = new MiroApi('ACCESS_TOKEN')
const boards = await api.getBoards()
See the documentation for a full list of methods.
FAQs
NodeJS client for Miro's REST API
The npm package @mirohq/miro-node receives a total of 0 weekly downloads. As such, @mirohq/miro-node popularity was classified as not popular.
We found that @mirohq/miro-node demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 7 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.
Security News
Newly introduced telemetry in devenv 1.4 sparked a backlash over privacy concerns, leading to the removal of its AI-powered feature after strong community pushback.