Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@dodi-smart/nuki-graphql-api
Advanced tools
This package creates a Nuki GraphQL API, allowing for interaction with data at Nuki. It is unofficial Nuki GraphQL API generated based on Nuki's Swagger OpenAPI specification, mainly configured to be used as Hasura Remote Schema.
Here's an example of how to use the Nuki GraphQL API to get a list of smart locks of the configured Nuki user:
query MyLocks {
nuki {
smartlocks {
name
smartlockId
state {
batteryCharge
state
}
firmwareVersion
hardwareVersion
}
}
}
It's recommended to add the Nuki GraphQL API as a Remote Schema in Hasura and connect data from your database with data in Nuki. By doing so, it's possible to request data from your database and Nuki in a single GraphQL query.
Here's an example of how to use the Nuki GraphQL API to get a list of smart locks for a specific Nuki user. Note that the user data is fetched from your database and the Nuki user data is fetched trough the Nuki API:
query UsersLocks {
users {
id
displayName
nukies {
# Remote schema relation in users table
name
smartlockId
state {
batteryCharge
state
}
firmwareVersion
hardwareVersion
}
}
}
APIs can be added upon request. PRs are welcome of course!
Api | Supported | Comment |
---|---|---|
Account | 🟠 | |
AccountSubscription | 🔴 | |
AccountUser | 🔴 | |
Address | 🔴 | |
AddressReservation | 🔴 | |
AddressToken | 🔴 | |
AdvancedApi | 🟠 | |
ApiKey | 🔴 | |
Company | 🔴 | |
Notification | 🔴 | |
Opener | 🔴 | |
Service | 🔴 | |
Smartlock | 🟠 | |
SmartlockAuth | 🔴 | |
SmartlockLog | 🟢 | Available nested inside smartlock query |
Subscription | 🔴 |
🟢 - Supported 🟠 - Partial 🔴 - Not supported
Install the package:
pnpm add @dodi-smart/nuki-graphql-api
Create a new Serverless Function: functions/graphql/nuki.ts
:
import { createNukiGraphQLServer } from '@dodi-smart/nuki-graphql-api'
const server = createNukiGraphQLServer({
graphiql: true,
graphqlEndpoint: '/graphql/nuki',
healthCheckEndpoint: '/graphql/nuki/health',
provideAuth(context) {
return {
// Should provide authentication
}
},
onUpdateSession(context, auth) {
// Handle session update
}
})
export default server
Go to Nuki Web and obtain OAuth2 API key and secret.
Click on Generate API token
, give the token name and check the scopes you want to use. Click save and copy the token value.
NUKI_CLIENT_ID
as an environment variable.NUKI_CLIENT_SECERT
as an environment variable.NUKI_API_KEY
as an environment variable.If you're using Nhost, add NUKI_CLIENT_ID
, NUKI_CLIENT_SECERT
and NUKI_API_KEY
to .env.development
like this:
NUKI_CLIENT_ID=6EYY••••
NUKI_CLIENT_SECERT=BPum••••
NUKI_API_KEY=59f6d••••
And add the production key values to environment variables in the Nhost dashboard.
nhost up
Learn more about the Nhost CLI.
Test the Nuki GraphQL API in the browser:
https://local.functions.nhost.run/v1/graphql/nuki
Add the Nuki GraphQL API as a Remote Schema in Hasura.
URL
{{NHOST_FUNCTIONS_URL}}/graphql/nuki
Headers
x-nhost-webhook-secret: NHOST_WEBHOOK_SECRET (From env var)
The
NHOST_WEBHOOK_SECRET
is used to verify that the request is coming from Nhost. The environment variable is a system environment variable and is always available.
You have several options to authentication your users agains Nuki using this library. All of them depends on the usecase:
Single user usecase (easy to setup)
When the system should work with the locks of a single user (administrator). Permissions and access to the locks are granted to others users via the administrator or using Hasura user roles.
Multi user usecase (advanced)
When system work with locks of multiple users. Each user can authenticate against Nuki using their own credentials via OAuth 2.0. This usecase can be used for multi tenant apps for example.
Use case | Using API_KEY (easy) | OAuth 2.0 (advanced) | OAuth 2.0 + ApiKeyToken (advanced) |
---|---|---|---|
Single user | 🟢 | 🟠 | 🟠 |
Multi user | 🔴 | 🟠 | 🟢 |
🟢 - Preferable way 🟠 - Supported 🔴 - Not supported
Go to Nuki Web and click on API on side navigation
Click on Generate API token
, give the token name and check the scopes you want to use. Click save and copy the token value.
ApiKeyToken
is long-living token and does not require refresh.
NUKI_API_KEY
as an environment variable.If you're using Nhost, add NUKI_API_KEY
to .env.development
like this:
NUKI_API_KEY=59f6d••••
And add the production key values to environment variables in the Nhost dashboard.
If you need to pass the API key from Hasura instead of having it as environment variable, then:
Add to the Hasura Remote Schema the API Key
x-nuki-api-key: NUKI_API_KEY (From env var)
The environment variable is a system environment variable and is always available.
import { createNukiGraphQLServer } from '@dodi-smart/nuki-graphql-api'
const server = createNukiGraphQLServer({
graphqlEndpoint: '/graphql/nuki',
healthCheckEndpoint: '/graphql/nuki/health',
provideAuth(context) {
const { request } = context
return {
// Is enough to pass just the accessToken
accessToken: request.headers.get('x-nuki-api-key')
}
},
onUpdateSession(context, auth) {
// Can be empty as NUKI_API_KEY are long-living tokens
}
})
export default server
Go to Nuki Web and click on API on side navigation
Point OAuth2 Redirect URL to a Nhost serverless function:
https://local.functions.nhost.run/v1/callback/nuki
Create a new Serverless Function: functions/callback/nuki.ts
:
import { createNukiOAuthCallback } from '@dodi-smart/nuki-graphql-api'
const handler = (req, res) => {
const {userId, accessToken, refreshToken} = createNukiOAuthCallback(req, res)
await gqlSDK.updateUserNukiAuth({
id: userId,
accessToken,
refreshToken
})
}
export default handler
import { createNukiGraphQLServer } from '@dodi-smart/nuki-graphql-api'
const server = createNukiGraphQLServer({
graphqlEndpoint: '/graphql/nuki',
healthCheckEndpoint: '/graphql/nuki/health',
provideAuth(context) {
const { userClaims } = context
const { user } = await gqlSDK.getUser({
id: userId
})
return {
// Example if nuki creds are saved in user's metadata, can differ
accessToken: user.metadata.nukiAccessToken,
refreshToken: user.metadata.nukiRefreshToken,
}
},
onUpdateSession(context, auth) {
const { userClaims } = context
const { accessToken, refreshToken } = auth
await gqlSDK.updateUserNukiAuth({
id: userId,
accessToken,
refreshToken
})
}
})
export default server
This is very similar to previous option with the different that after first login,
an ApiKeyToken
is automatically created and can be used instead of refreshing user session.
ApiKeyToken
is long-living token and does not require refresh or anything.
Go to Nuki Web and click on API on side navigation
Point OAuth2 Redirect URL to a Nhost serverless function:
https://local.functions.nhost.run/v1/callback/nuki
Api key creation can be enabled via environment variable or via code. If you like to use env variable follow the steps below, skip the section and check how to enable it via the function code.
NUKI_API_KEY_CREATE
as an environment variable.If you're using Nhost, add NUKI_API_KEY_CREATE
to .env.development
like this:
NUKI_API_KEY_CREATE=true
Create a new Serverless Function: functions/callback/nuki.ts
:
import { createNukiOAuthCallback } from '@dodi-smart/nuki-graphql-api'
const handler = (req, res) => {
const {userId, apiKeyToken} = createNukiOAuthCallback(req, res, true)
await gqlSDK.updateUserNukiAuth({
id: userId,
apiKey: apiKeyToken
})
}
export default handler
import { createNukiGraphQLServer } from '@dodi-smart/nuki-graphql-api'
const server = createNukiGraphQLServer({
graphqlEndpoint: '/graphql/nuki',
healthCheckEndpoint: '/graphql/nuki/health',
provideAuth(context) {
const { userClaims } = context
const { user } = await gqlSDK.getUser({
id: userId
})
return {
// Example if nukiApiKey is saved in user's metadata, can differ
accessToken: user.metadata.nukiApiKey,
}
},
onUpdateSession(context, auth) {
// Can be empty as API Keys are long-living tokens
}
})
export default server
Here's a minimal example without any custom permissions. Only requests using the x-hasura-admin-secret
header will work:
import { createNukiGraphQLServer } from '@dodi-smart/nuki-graphql-api'
const server = createNukiGraphQLServer({
graphqlEndpoint: '/graphql/nuki',
healthCheckEndpoint: '/graphql/nuki/health',
provideAuth(context) {
/* ... */
},
onUpdateSession(context, auth) {
/* ... */
}
})
export default server
For more granular permissions, you can pass an isAllowed
function to the createNukiGraphQLServer
. The isAllowed
function takes a context
as parameter and runs every time the GraphQL server makes a request to Nuki to get or modify data for a specific Nuki user.
Here is an example of an isAllowed
function:
import { createNukiGraphQLServer } from '@dodi-smart/nuki-graphql-api';
const isAllowed = (context: Context) => {
const { isAdmin, userClaims } = context
// allow all requests if they have a valid `x-hasura-admin-secret`
if (isAdmin) {
return true
}
// get user id
const userId = userClaims['x-hasura-user-id']
// check if the user is signed in
if (!userId) {
return false
}
// get more user information from the database
const { user } = await gqlSDK.getUser({
id: userId
})
if (!user) {
return false
}
// other checks
}
const server = createNukiGraphQLServer({
graphqlEndpoint: '/graphql/nuki',
healthCheckEndpoint: '/graphql/nuki/health',
isAllowed,
provideAuth(context) {
/* ... */
},
onUpdateSession(context, auth) {
/* ... */
}
});
export default server;
The context
object contains:
userClaims
- verified JWT claims from the user's access token.isAdmin
- true
if the request was made using a valid x-hasura-admin-secret
header.request
- Fetch API Request object that represents the incoming HTTP request in platform-independent way. It can be useful for accessing headers to authenticate a userquery
- the DocumentNode that was parsed from the GraphQL query stringoperationName
- the operation name selected from the incoming queryvariables
- the variables that were defined in the queryextensions
- the extensions that were received from the clientRead more about the default context from GraphQL Yoga.
FAQs
Nuki GraphQL API
The npm package @dodi-smart/nuki-graphql-api receives a total of 0 weekly downloads. As such, @dodi-smart/nuki-graphql-api popularity was classified as not popular.
We found that @dodi-smart/nuki-graphql-api demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.