Skip to content

Authorization and integrity

Flows can check authorization by inspecting the context property passed to the flow function. It is up to the framework integration (like genkit_shelf) to populate this context.

import 'package:genkit/genkit.dart';
import 'package:schemantic/schemantic.dart';
part 'self_summary.g.dart'; // Generated by build_runner
// Define the input schema
@Schema()
abstract class $SelfSummaryInput {
String get uid;
}
// Define the output schema
@Schema()
abstract class $SelfSummaryOutput {
String get profileSummary;
}
final selfSummaryFlow = ai.defineFlow(
name: 'selfSummaryFlow',
inputSchema: SelfSummaryInput.$schema,
outputSchema: SelfSummaryOutput.$schema,
fn: (input, context) async {
final auth = context.context?['auth'];
if (auth == null) {
throw GenkitException('Unauthenticated', status: StatusCodes.UNAUTHENTICATED);
}
// Access typed properties on the generated concrete class
if (input.uid != auth['uid']) {
throw GenkitException('You may only summarize your own profile data.', status: StatusCodes.PERMISSION_DENIED);
}
// Flow logic here...
return SelfSummaryOutput(profileSummary: 'User profile summary would go here');
},
);

You can verify this logic by manually passing context during execution:

// Error: Unauthenticated
await selfSummaryFlow(SelfSummaryInput(uid: 'abc-def'));
// Error: Permission denied
await selfSummaryFlow(
SelfSummaryInput(uid: 'abc-def'),
context: {'auth': {'uid': 'hij-klm'}},
);
// Success
await selfSummaryFlow(
SelfSummaryInput(uid: 'abc-def'),
context: {'auth': {'uid': 'abc-def'}},
);

When deploying with genkit_shelf (running as a server), you can use a ContextProvider to verify incoming requests and populate the context.

import 'dart:async';
import 'package:genkit/genkit.dart';
import 'package:genkit_shelf/genkit_shelf.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
FutureOr<Map<String, dynamic>> apiKeyContextProvider(Request request) {
final authHeader = request.headers['Authorization'];
if (authHeader == null || !authHeader.startsWith('Bearer ')) {
// Throwing here will result in a 403 Forbidden response
throw GenkitException('Missing API Key', status: StatusCodes.UNAUTHENTICATED);
}
final token = authHeader.substring(7);
if (token != 'REQUIRED_API_KEY') {
throw GenkitException('Invalid API Key', status: StatusCodes.PERMISSION_DENIED);
}
return {
'auth': {'uid': 'admin', 'key': token}
};
}
void main() async {
final ai = Genkit(plugins: []);
// ... define flow ...
final handler = const Pipeline()
.addMiddleware(logRequests())
.addHandler(shelfHandler(selfSummaryFlow, contextProvider: apiKeyContextProvider));
await io.serve(handler, 'localhost', 3400);
}