Experimental OIDC4VC API wrapped in an AI Agent

This is an experimental implementation of the OIDC4VP protocol, featuring integration with OpenAI GPT-4 Turbo.

You can see a demo here.

To use this API for free, please contact us to request access credentials as client_id and client_secret.

Verifier API – Agent-Assisted Credential Presentation

βœ… Overview

This API defines a new generation of Verifier APIs that extend OpenID Connect protocol to support agent-assisted Verifiable Credential presentation.

πŸ” Bridge Architecture:
This API acts as a bridge between the verifier application (using standard OpenID Connect)
and the user's digital wallet (using OIDC4VP – OpenID Connect for Verifiable Presentations).
It allows existing OIDC-compatible systems to request and verify credentials without needing direct
integration with the wallet's native protocol.

Supports:

🧠 Agent Assistance Levels

This allows to define the nature of the AI Agent assistance within the flow. If level 0 then no AI Agent at all, the QRCode is displayed as a standard OIDC4VP flow.

LevelDescription
0No help, completely passive.
1Respond only to direct help requests.
2Minimal help if user is stuck.
3Brief reminders without details.
4Subtle hints at key steps.
5Comments and light guidance.
6Anticipate and correct minor mistakes.
7Suggest next steps, user decides.
8Start actions with user confirmation.
9Lead the session, user approves steps.
10Fully automate the flow.

🧾 Core Agent Instructions

  1. Begin with a welcoming conversation.
  2. Ask for given_name, family_name, and birth_date. If available, retrieve from the wallet.
  3. Ask permission before triggering the wallet (QR on desktop, button on mobile).
  4. If user says they don’t have a wallet, do not show or mention a QR code.
  5. If data is not verified, ask if they can provide it from their wallet.
  6. As soon as you have verified values, call:
return_to_app(VC_data_depending on_the_vc_type);

πŸ” API Usage

Authorization Request Parameters

ParameterRequiredDescription
client_idβœ…Verifier’s client ID
response_typeβœ…code or id_token
scopeβœ…Credential types (e.g., openid pid)
redirect_uriβœ…Verifier's redirect URL
stateβœ…Opaque session token
agent_assistance_levelOptionalLevel of agent guidance (0–10)

Accepted Scope Values

The scopes are associated to VC type.

πŸ“€ Example Authorization Request

curl -X GET "https://verifier.wallet-provider.com/authorize?client_id=verifier123&response_type=code&scope=openid%20pid&redirect_uri=https%3A%2F%2Fverifier.example.com%2Fcallback&state=abc123&agent_assistance_level=7"

🧭 Standard OIDC Endpoints

EndpointDescription
/.well-known/openid-configurationDiscovery metadata
/authorizeAuthorization start
/tokenToken exchange
/userinfoUser or credential info
/jwks.jsonPublic keys

Example: Python (pyoidc)


  from flask import Flask, jsonify, render_template, redirect, request, session
  from flask_session import Session
  from flask_pyoidc import OIDCAuthentication
  from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientMetadata
  from flask_pyoidc.user_session import UserSession
  import redis
  import json
  
  # Initialize Redis client
  red = redis.Redis(host='localhost', port=6379, db=0)
  
  # Init Flask
  app = Flask(__name__)
  app.config.update(
      OIDC_REDIRECT_URI='http://192.168.0.65:5000/callback',  # Update with ngrok for testing
      SECRET_KEY="lkjhlkjh"
  )
  
  # Session config with Redis backend
  app.config['SESSION_PERMANENT'] = True
  app.config['SESSION_COOKIE_NAME'] = 'talao'
  app.config['SESSION_TYPE'] = 'redis'
  app.config['SESSION_REDIS'] = red  
  
  sess = Session(app)
  
  # Configure OpenID Connect
  client_metadata = ClientMetadata(
      client_id='your_client_id',          # contact us
      client_secret='your_client_secret'   # contact us
  )
  
  provider_config = ProviderConfiguration(
      issuer='https://verifier.wallet-provider.com/api/app',
      client_metadata=client_metadata,
      auth_request_params={
          'scope': ['openid', 'pid'],
          'agent_assistance_level': 7
      }
  )
  
  auth = OIDCAuthentication({'default': provider_config}, app)
  
  @app.route('/', methods=['GET', 'POST'])
  def site():
      if request.method == 'GET':
          return render_template("site.html")  # Should include a button to POST to /
      else:
          session.clear()
          return redirect('/login')
  
  @app.route('/login')
  @auth.oidc_auth('default')
  def index():
      user_session = UserSession(session)
      print("Id token = ", user_session.id_token)  # ID token contents
      return render_template('token.html', token=json.dumps(user_session.id_token, indent=4))
  
  @auth.error_view
  def error(error=None, error_description=None):
      return jsonify({'error': error, 'description': error_description or "Sorry"})
  
  if __name__ == '__main__':
      app.run(host="192.168.0.65", port=5000, debug=True)  # Use ngrok for external tests