Ontwerp een Geavanceerd GraphQL Schema met Geavanceerde Authorization en Toegangsbeheer
description
Met deze prompt kun je een veilig en flexibel GraphQL schema ontwerpen dat complexe toegangsregels ondersteunt. Het helpt je om toepassingen te bouwen die voldoen aan strenge beveiligingsvereisten en tegelijkertijd schaalbaar en onderhoudbaar blijven. Dit lost problemen op rondom ongeautoriseerde toegang en zorgt voor een robuuste architectuur, beter dan standaard schema ontwerpen zonder toegangscontrole.
prompt
Help me een geavanceerd GraphQL schema te ontwerpen dat complexe authorization en toegangsbeheer ondersteunt. Mijn domein is: <beschrijf je domein of toepassingsgebied>. Ik wil ondersteuning voor: <specificeer gewenste authorization methoden zo ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een voorbeeld van een geavanceerd GraphQL-schema voor het domein Financiële dienstverlening met gevoelige klantgegevens, inclusief rolgebaseerde toegangscontrole en best practices:
1. Schema-definitie met toegangscontrole directives
2. Rollen en authenticatie
3. Implementatie-ideeën en best practices
---
**1. Schema-definitie**
Gebruik custom directives voor toegangscontrole:
```graphql
directive @auth(requires: Role = USER) on FIELD_DEFINITION | OBJECT
enum Role {
ADMIN
USER
GUEST
}
type Klant @auth(requires: USER) {
id: ID!
naam: String! @auth(requires: USER)
geboortedatum: String! @auth(requires: USER)
saldo: Float! @auth(requires: ADMIN)
transacties: [Transactie!]! @auth(requires: USER)
}
type Transactie {
id: ID!
datum: String!
bedrag: Float!
description: String
}
type Query {
klant(id: ID!): Klant @auth(requires: USER)
alleKlanten: [Klant!]! @auth(requires: ADMIN)
}
```
**2. Implementatie van toegangscontrole**
- Voeg een middleware of resolver-wrapper toe die de `@auth` directive leest en controleert of de huidige gebruiker de juiste rol heeft.
- Bijvoorbeeld, in Apollo Server kan je een schema-directive maken:
```js
class AuthDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const { requires } = this.args;
const { resolve = defaultFieldResolver } = field;
field.resolve = async function (...args) {
const context = args[2];
if (!context.user || !context.user.roles.includes(requires)) {
throw new Error('Toegang geweigerd');
}
return resolve.apply(this, args);
};
}
}
```
**3. Authenticatie en rolbeheer**
- Beheer gebruikersrollen via een beveiligd identity management systeem.
- Gebruik JWT tokens met claims over rollen.
- Bij elke request wordt het token geverifieerd en de gebruiker geïdentificeerd.
**4. Best practices en schaalbaarheid**
- **Fine-grained toegangscontrole:** Gebruik directives voor verschillende velden en objecten, zodat je complexe regels kunt implementeren.
- **Centraliseer autorisatie logic:** Plaats alle autorisaties in middleware of directives, niet in de resolvers zelf.
- **Caching:** Wees voorzichtig met caching, omdat toegangscontrole dynamisch kan zijn. Gebruik eventueel gescheiden cache-lagen per rol.
- **Audit logs:** Log alle toegangsverzoeken en -fouten voor compliance.
- **Schema evolutie:** Ontwerp het schema flexibel zodat nieuwe rollen of regels eenvoudig kunnen worden toegevoegd.
---
**Kort samengevat:**
- Gebruik schema directives voor toegangscontrole.
- Beheer rollen en authenticatie via een secure identity provider.
- Controleer rollen in middleware/directives.
- Pas best practices toe voor schaalbaarheid en beveiliging.
Heeft u specifieke onderdelen of voorbeelden nodig?
provider: deepseek
model: deepseek-chat
Zeker, hieronder vindt u een geavanceerd GraphQL schema-ontwerp voor financiële dienstverlening met robuust autorisatiebeheer.
---
### **GraphQL Schema Definitie**
```graphql
# Basistypes en authenticatie
scalar DateTime
scalar EmailAddress
scalar IBAN
type Mutation {
login(email: EmailAddress!, wachtwoord: String!): AuthPayload!
refreshToken: AuthPayload!
logout: Boolean!
}
type AuthPayload {
token: String!
vervaltOp: DateTime!
gebruiker: Gebruiker!
}
# Gebruikersmanagement
type Gebruiker {
id: ID!
email: EmailAddress!
rol: GebruikersRol!
profiel: GebruikersProfiel!
laatsteLogin: DateTime
gemaakteRekeningen: [Rekening!]!
}
type GebruikersProfiel {
voornaam: String!
achternaam: String!
telefoon: String
}
enum GebruikersRol {
ADMIN
FINANCEEL_BEHEERDER
KLANTENSERVICE
GEBRUIKER
AUDITOR
}
# Financiële gegevens
type Rekening {
id: ID!
iban: IBAN!
saldo: Float!
valuta: Valuta!
eigenaar: Gebruiker!
transacties(
vanaf: DateTime
tot: DateTime
eerste: Int
na: String
): TransactieVerbinding!
gevoelig: GevoeligeRekeningGegevens! @auth(requires: [ADMIN, FINANCEEL_BEHEERDER])
}
type GevoeligeRekeningGegevens {
kredietlimiet: Float!
rentepercentage: Float!
producttype: RekeningType!
}
enum RekeningType {
ZAKELIJK
PARTICULIER
SPAAR
BELEGGING
}
enum Valuta {
EUR
USD
GBP
}
type Transactie {
id: ID!
bedrag: Float!
valuta: Valuta!
tegenpartij: Tegenpartij!
omschrijving: String!
datum: DateTime!
categorie: TransactieCategorie!
}
type Tegenpartij {
naam: String!
iban: IBAN!
}
enum TransactieCategorie {
INKOMST
UITGAVE
OVERBOEKING
INCASSO
}
type TransactieVerbinding {
paginaInfo: PaginaInfo!
edges: [TransactieEdge!]!
}
type TransactieEdge {
node: Transactie!
cursor: String!
}
type PaginaInfo {
heeftVolgendePagina: Boolean!
endCursor: String
}
# Query definitie met autorisatie
type Query {
# Algemene queries
mij: Gebruiker! @auth
rekeningen: [Rekening!]! @auth
# Beheerder-queries
alleGebruikers: [Gebruiker!]! @auth(requires: [ADMIN, AUDITOR])
rekeningDetails(id: ID!): Rekening! @auth
transactieRapport(
rekeningId: ID!
vanaf: DateTime!
tot: DateTime!
): [Transactie!]! @auth(requires: [ADMIN, FINANCEEL_BEHEERDER])
}
# Directives voor autorisatie
directive @auth(
requires: [GebruikersRol!] = [GEBRUIKER]
) on FIELD_DEFINITION
```
---
### **Implementatie Best Practices**
#### 1. **Autorisatie Laag**
```javascript
// authorisation.js
class Authorisation {
static heeftToegang(context, benodigdeRollen) {
const { gebruiker } = context;
if (!gebruiker) throw new Error('Niet geauthenticeerd');
if (benodigdeRollen.includes(gebruiker.rol)) return true;
// Hiërarchische rechten controle
const rechtenHiërarchie = {
ADMIN: ['ADMIN', 'FINANCEEL_BEHEERDER', 'KLANTENSERVICE', 'AUDITOR', 'GEBRUIKER'],
FINANCEEL_BEHEERDER: ['FINANCEEL_BEHEERDER', 'GEBRUIKER'],
KLANTENSERVICE: ['KLANTENSERVICE', 'GEBRUIKER'],
AUDITOR: ['AUDITOR'],
GEBRUIKER: ['GEBRUIKER']
};
return rechtenHiërarchie[gebruiker.rol]?.some(rol =>
benodigdeRollen.includes(rol)
) || false;
}
}
```
#### 2. **Field-level Autorisation Middleware**
```javascript
// schema.js
const { mapSchema, getDirective, MapperKind } = require('@graphql-tools/utils');
function authDirectiveTransformer(schema) {
return mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
const authDirective = getDirective(schema, fieldConfig, 'auth');
if (!authDirective) return fieldConfig;
const { requires } = authDirective[0];
const originalResolver = fieldConfig.resolve;
fieldConfig.resolve = async (source, args, context, info) => {
if (!Authorisation.heeftToegang(context, requires)) {
throw new Error('Onvoldoende rechten');
}
// Data filtering op resultaatniveau
const result = await originalResolver(source, args, context, info);
return filterGevoeligeGegevens(result, context.gebruiker.rol);
};
return fieldConfig;
}
});
}
function filterGevoeligeGegevens(data, rol) {
if (rol !== 'ADMIN' && data?.gevoelig) {
const { gevoelig, ...rest } = data;
return rest;
}
return data;
}
```
#### 3. **Context Initialisatie**
```javascript
// context.js
async function createContext({ req }) {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return { gebruiker: null };
try {
const decoded = verifyJWT(token);
const gebruiker = await GebruikerService.vindBijId(decoded.userId);
return {
gebruiker,
rol: gebruiker.rol,
permissions: await haalPermissionsOp(gebruiker.rol)
};
} catch (error) {
throw new AuthenticationError('Ongeldig token');
}
}
```
---
### **Schaalbaarheidsstrategieën**
#### 1. **Distributed Caching**
```javascript
// cached-resolvers.js
const redis = new Redis(process.env.REDIS_URL);
const rekeningenResolver = async (parent, args, context) => {
const cacheKey = `rekeningen:${context.gebruiker.id}`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
const result = await RekeningService.vindVoorGebruiker(context.gebruiker.id);
await redis.setex(cacheKey, 300, JSON.stringify(result)); // 5 min cache
return result;
};
```
#### 2. **DataLoader Pattern**
```javascript
// dataloaders.js
const gebruikerLoader = new DataLoader(async (ids) => {
const gebruikers = await GebruikerService.vindBijIds(ids);
return ids.map(id => gebruikers.find(u => u.id === id));
});
const rekeningLoader = new DataLoader(async (gebruikerIds) => {
return Promise.all(
gebruikerIds.map(id => RekeningService.vindVoorGebruiker(id))
);
});
```
#### 3. **Query Complexity Limiet**
```javascript
// complexity.js
const complexityLimit = {
maximumComplexity: 1000,
onComplete: (complexity) => {
if (complexity > 1000) {
throw new Error('Query te complex');
}
}
};
```
---
### **Beveiligingsmaatregelen**
1. **JWT Tokens** met korte expiry times (15-30 minuten)
2. **Refresh tokens** met strict server-side storage
3. **Rate limiting** per gebruiker en IP
4. **Query depth limiting** (max 10 levels)
5. **Input validation** met custom scalars
6. **Audit logging** van alle gevoelige operaties
7. **Encryptie** van gevoelige data at rest en in transit
---
### **Monitoring en Logging**
```javascript
// audit-logger.js
class AuditLogger {
static logToegang(gebruiker, operatie, metadata = {}) {
logger.info({
type: 'TOEGANGS_CONTROLE',
timestamp: new Date().toISOString(),
gebruikerId: gebruiker.id,
operatie,
metadata
});
}
}
// Gebruik in resolvers
AuditLogger.logToegang(context.gebruiker, 'REKENING_BEKIJKEN', {
rekeningId: args.id,
succesvol: true
});
```
Dit schema biedt een schaalbare, veilige basis voor financiële toepassingen met gedetailleerd toegangsbeheer op veld- en operationeel niveau.
error: Generation failed [deepseek] prompt_id=2985 locale=de err=DeepSeek connection/timeout | Generation failed [deepseek] prompt_id=2985 locale=fr err=DeepSeek connection/timeout