Skip to main content

Custom Scopes

How to request and handle custom identity blocks (scopes).

Requesting Custom Scopes

In Settings

Configure default scopes in settings.py:

# settings.py
SVA_OAUTH_SCOPES = 'openid email profile username name phone address bio social images'

Dynamically

Request scopes dynamically per request:

from sva_oauth_client.client import SVAOAuthClient
from django.conf import settings

def login_with_custom_scopes(request, scopes):
"""Login with custom scopes"""
client = SVAOAuthClient(
base_url=settings.SVA_OAUTH_BASE_URL,
client_id=settings.SVA_OAUTH_CLIENT_ID,
client_secret=settings.SVA_OAUTH_CLIENT_SECRET,
redirect_uri=settings.SVA_OAUTH_REDIRECT_URI,
data_token_secret=settings.SVA_DATA_TOKEN_SECRET,
scopes=scopes, # Custom scopes
)

auth_url, code_verifier = client.get_authorization_url()
request.session['code_verifier'] = code_verifier
return redirect(auth_url)

Available Scopes

Core Identity

  • openid - Required for OIDC
  • email - Email address
  • profile - Basic profile (name, username, bio, images)
  • username - Username
  • name - Full name
  • bio - Bio/description
  • pronoun - Pronouns
  • dob - Date of birth

Contact Information

  • phone - Phone number
  • address - Address information
  • social - Social media links

Profile Information

  • images - Profile images
  • skills - Skills list
  • hobby - Hobbies

Verified Identity Documents

  • pan_card - PAN card
  • aadhar - Aadhaar card
  • driving_license - Driving license
  • voter_id - Voter ID
  • passport - Passport

Professional Information

  • education - Education history
  • employment - Employment history
  • professional_license - Professional licenses

Financial Information

  • crypto_wallet - Crypto wallet addresses

Scope Combinations

Basic Profile

SVA_OAUTH_SCOPES = 'openid email profile'

Gets: email, name, username, bio, images

Complete Profile

SVA_OAUTH_SCOPES = 'openid email profile username name phone address bio social images'

Gets: All profile information

Professional Profile

SVA_OAUTH_SCOPES = 'openid email profile name phone education employment professional_license'

Gets: Professional information

Identity Verification

SVA_OAUTH_SCOPES = 'openid email profile pan_card aadhar driving_license'

Gets: Verified identity documents

Handling Custom Blocks

Check for Block Availability

from sva_oauth_client.decorators import sva_oauth_required
from sva_oauth_client.utils import get_sva_claims

@sva_oauth_required
def my_view(request):
claims = get_sva_claims(request)

# Check if specific blocks are available
has_pan = 'pan_card' in claims
has_aadhar = 'aadhar' in claims
has_education = 'education' in claims

context = {
'has_pan': has_pan,
'has_aadhar': has_aadhar,
'has_education': has_education,
}

# Add block data if available
if has_pan:
context['pan_card'] = claims['pan_card']

return render(request, 'template.html', context)

Require Custom Blocks

from sva_oauth_client.decorators import sva_blocks_required

@sva_blocks_required('email', 'pan_card', 'aadhar')
def kyc_view(request):
"""KYC verification view requiring PAN and Aadhaar"""
claims = get_sva_claims(request)

# All blocks are guaranteed to exist
return render(request, 'kyc.html', {
'email': claims['email'],
'pan_card': claims['pan_card'],
'aadhar': claims['aadhar'],
})

Complex Block Structures

Address Block

address = claims.get('address')
if address:
street = address.get('street')
city = address.get('city')
state = address.get('state')
zip_code = address.get('zip')
country = address.get('country')

Social Block

social = claims.get('social')
if social:
twitter = social.get('twitter')
github = social.get('github')
linkedin = social.get('linkedin')

Education Block

education = claims.get('education')
if education:
# education is typically a list
for edu in education:
degree = edu.get('degree')
institution = edu.get('institution')
year = edu.get('year')

Employment Block

employment = claims.get('employment')
if employment:
# employment is typically a list
for emp in employment:
company = emp.get('company')
position = emp.get('position')
start_date = emp.get('start_date')
end_date = emp.get('end_date')

Dynamic Scope Selection

Allow users to choose what to share:

def scope_selection_view(request):
"""Let user choose scopes before login"""
if request.method == 'POST':
selected_scopes = request.POST.getlist('scopes')
scopes_string = ' '.join(['openid'] + selected_scopes)

# Store selected scopes in session
request.session['selected_scopes'] = scopes_string

# Redirect to login with custom scopes
return redirect('custom_oauth_login')

return render(request, 'scope_selection.html')

def custom_oauth_login(request):
"""Login with user-selected scopes"""
scopes = request.session.get('selected_scopes', 'openid email profile')

client = SVAOAuthClient(
# ... client config
scopes=scopes,
)

auth_url, code_verifier = client.get_authorization_url()
request.session['code_verifier'] = code_verifier
return redirect(auth_url)

Scope Validation

Validate that required scopes are present:

def validate_scopes(claims, required_scopes):
"""Validate that required scopes are present in claims"""
missing = []

for scope in required_scopes:
if scope not in claims:
missing.append(scope)

return missing

@sva_oauth_required
def my_view(request):
claims = get_sva_claims(request)

required = ['email', 'name', 'phone']
missing = validate_scopes(claims, required)

if missing:
messages.warning(request, f'Missing required data: {", ".join(missing)}')
return redirect('sva_oauth_client:login')

# All required scopes are present
return render(request, 'template.html', {'claims': claims})

Next Steps