Skip to content

Commit 1bfbf91

Browse files
pottisSuresh Potti
andauthored
Update to explainer for Structured data support (#786)
* addressed review comments * addressed review comments --------- Co-authored-by: Suresh Potti <[email protected]>
1 parent fae1909 commit 1bfbf91

File tree

1 file changed

+107
-60
lines changed

1 file changed

+107
-60
lines changed

explorations/structured_data_support.md

Lines changed: 107 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -30,94 +30,141 @@ Allow the `token` field to accept any valid JSON type (`any`) instead of restric
3030

3131
#### 1. ID Assertion Endpoint Response
3232

33-
The `token` field type changes from `string` to `any`, allowing structured JSON objects.
34-
35-
#### 2. IdentityProvider.resolve() Parameter Type
36-
37-
**Before:**
38-
```typescript
39-
interface IdentityProvider {
40-
resolve(token: string): Promise<IdentityCredential>;
33+
**Current (String only):**
34+
```json
35+
{
36+
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
4137
}
4238
```
4339

44-
**After:**
45-
```typescript
46-
interface IdentityProvider {
47-
resolve(token: any): Promise<IdentityCredential>;
40+
**Proposed (Any JSON type):**
41+
```json
42+
{
43+
"token": {
44+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
45+
"refresh_token": "def50200f3d5b...",
46+
"expires_in": 3600,
47+
"token_type": "Bearer"
48+
}
4849
}
4950
```
5051

51-
#### 3. IdentityCredential.token Property Type
52+
#### 2. JavaScript API Usage
5253

53-
**Before:**
54-
```typescript
55-
interface IdentityCredential {
56-
readonly token: string;
57-
// ... other properties
58-
}
54+
**Current (Manual parsing required):**
55+
```javascript
56+
const credential = await navigator.credentials.get({...});
57+
// Must manually parse string token
58+
const tokenData = JSON.parse(credential.token);
59+
const accessToken = tokenData.access_token;
5960
```
6061

61-
**After:**
62-
```typescript
63-
interface IdentityCredential {
64-
readonly token: any;
65-
// ... other properties
66-
}
62+
**Proposed (Direct access):**
63+
```javascript
64+
const credential = await navigator.credentials.get({...});
65+
// Direct access to structured data
66+
const accessToken = credential.token.access_token;
67+
const expiresIn = credential.token.expires_in;
6768
```
6869

6970
## Design Decisions and Alternatives Considered
7071

71-
This section addresses key design questions and explains why alternative approaches were rejected.
72+
This section addresses key design questions and explains how alternative approaches would look in practice.
7273

7374
### Why a Unified `any` Type Instead of Separate Fields?
7475

75-
**Rejected Alternative**: Adding a `structured_data` field alongside the existing `token` field.
76-
77-
**Decision Rationale**: A unified approach with `any` type is superior because:
78-
- **Eliminates API complexity**: No confusion about which field to use or precedence rules
79-
- **Prevents ecosystem fragmentation**: Single token field ensures consistent adoption
80-
- **Enables seamless migration**: IDPs can evolve from strings to objects naturally
81-
- **Maintains type system alignment**: `any` encompasses both strings and objects
76+
**Rejected Alternative - Separate Fields Approach:**
77+
```json
78+
{
79+
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
80+
"structured_data": {
81+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
82+
"expires_in": 3600
83+
}
84+
}
85+
```
8286

83-
### Why No Type Indicator Attribute?
87+
**Problems with this approach:**
88+
- Which field should RPs use? What if both are present?
89+
- IDPs might feel compelled to populate both fields
90+
- Creates ecosystem fragmentation
8491

85-
**Rejected Alternative**: Adding a `token_format` field to indicate payload type.
92+
**Proposed Unified Approach:**
93+
```json
94+
{
95+
"token": {
96+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
97+
"expires_in": 3600
98+
}
99+
}
100+
```
86101

87-
**Decision Rationale**: Type indicators are unnecessary because:
88-
- **JSON is self-describing**: Runtime type detection via `typeof` is simple and reliable
89-
- **Avoids additional complexity**: No extra fields to validate or maintain
90-
- **Reduces fragility**: No risk of mismatched indicators and actual data
102+
**Benefits:**
103+
- Single source of truth eliminates confusion
104+
- Natural migration path from strings to objects
105+
- Backward compatible (strings remain valid)
91106

92-
### What About Compatibility with Existing IDPs?
107+
### Why No Type Indicator Attribute?
93108

94-
**Compatibility Risk**: Minimal to zero - this change is fully backward compatible.
109+
**Rejected Alternative - Type Indicator Approach:**
110+
```json
111+
{
112+
"token_format": "structured",
113+
"token": {
114+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
115+
"expires_in": 3600
116+
}
117+
}
118+
```
95119

96-
**Key Points**:
97-
- String tokens remain valid (strings are valid JSON types)
98-
- No breaking changes to existing API contracts
99-
- Zero forced migration required
100-
- IDPs can adopt structured tokens at their own pace
120+
**Problems with this approach:**
121+
- Adds unnecessary complexity
122+
- Risk of mismatched indicators and actual data
123+
- JSON is already self-describing
101124

102-
### Why Not Support Both String and Structured Formats Simultaneously?
125+
**Proposed Approach (No indicator needed):**
126+
```javascript
127+
// Simple runtime detection
128+
if (typeof credential.token === 'string') {
129+
// Handle string token
130+
} else {
131+
// Handle structured token
132+
}
133+
```
103134

104-
**Rejected Alternative**: Allowing both formats in the same response.
135+
### What About Compatibility with Existing IDPs?
105136

106-
**Decision Rationale**: Single format approach is better because:
107-
- **Eliminates precedence ambiguity**: Clear which token value is authoritative
108-
- **Reduces security risks**: Fewer code paths mean fewer vulnerabilities
109-
- **Simplifies validation**: Single validation path reduces error opportunities
110-
- **Improves developer experience**: Cleaner, more predictable API behavior
137+
**Current IDPs (continue working unchanged):**
138+
```json
139+
{
140+
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
141+
}
142+
```
111143

112-
### Rejected Alternatives Summary
144+
**New IDPs can use structured format:**
145+
```json
146+
{
147+
"token": {
148+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
149+
"expires_in": 3600
150+
}
151+
}
152+
```
113153

114-
1. **Do Nothing**: Poor developer ergonomics and competitiveness
115-
2. **Separate Fields**: API complexity and developer confusion
116-
3. **Type Indicators**: Unnecessary overhead when JSON is self-describing
117-
4. **Dual Format Support**: Security risks and validation complexity
118-
5. **Content Negotiation**: HTTP layer complexity without addressing type system issues
154+
**RPs can handle both:**
155+
```javascript
156+
let tokenData;
157+
if (typeof credential.token === 'string') {
158+
tokenData = JSON.parse(credential.token);
159+
} else {
160+
tokenData = credential.token;
161+
}
162+
```
119163

120-
**Recommended compatibility approaches**: Version-based endpoints, client capability detection, or gradual migration strategies.
164+
**Benefits:**
165+
- Clear semantics with single authoritative value
166+
- Simpler validation and fewer security risks
167+
- Better developer experience
121168

122169
## Benefits
123170

0 commit comments

Comments
 (0)