Skip to content

Conversation

@4gust
Copy link
Collaborator

@4gust 4gust commented Sep 25, 2025

Summary

This PR introduces a comprehensive design specification for implementing Federated Managed Identity (FMI) support in MSAL Go, addressing directory-less identity scenarios for high-cardinality use cases.

Key Features Designed

  • Cache Extensibility: Extends existing AccessToken struct and Key() method to support FMI path hashing
  • FMI Authentication Flows: Support for all 5 FMI flows (RMA credential/token acquisition, FMI-to-FMI flows)
  • External Attributes: Attribute token validation and federated claims integration
  • Backward Compatibility: Zero breaking changes to existing MSAL Go APIs

Implementation Approach

  • Phase 1: Cache key extensions for FMI paths
  • Phase 2-4: FMI flows, attribute tokens, and federated claims
  • Phase 5: Testing and documentation

Files Added

  • fmi-msal-go-spec.md - Complete design specification with architecture, API design, and implementation phases

Documentation: Full spec included in this PR
Breaking Changes: None - additive functionality only

│ Public API Layer │
│ │
│ confidential.New() + WithFMIPath() │
│ .AcquireTokenForClient(WithAttributeTokens()) │
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not plan to enable attribute tokens at this time. Only attributes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it should be a method similar to WithFMIPath(), at the same level.

└─────────────────┘

FMI Flows:
Flow 1: Certificate → FMI Credential
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really a certificate exchange for an FMI credential. It's the RMA, who has a credential registered in the dir (e.g. a cert), is able to issue credentials for it's children, who are not present in the directory.

Flow 1 is "RMA gets an FMI cred, for a leaf entity or for a sub-RMA"
Flow 2 is "RMA gets an FMI token for a leaf entity"
Flow 3 is "sub-RMA, who has an FMI credential, gets an FMI credential for a child sub-RMA"
Flow 5 is correct, and the most important one.

}

// NEW: Add FMI path hash to key for FMI tokens
if a.FMIPathHash != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend a different design - the access token has a set of primary key components (ClietnID, Scopes etc). You now want to add a set of additional key components, which is a dictionary of { name, val } pairs.

This way, the caching logic remains decoupled from other parts of MSAL. The other parts of MSAL just have to say "fmi_path=xyz is now part of the cache key".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I understand. Let me update that with the new design

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And btw, attributes should be part of the cache key.

}

// Utility function to generate FMI path hash (SHA256, base64url encoded)
func generateFMIPathHash(fmiPath string) string {
Copy link
Member

@bgavrilMS bgavrilMS Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MSAL.NET spec states that you should also hash the key, not just the value.

e.g. new key components: ,

  1. Order the dictionary - "attributes=bla bla" "fmi_path=xyz"
  2. Create a string - attributesbla blafmi_pathxyz
  3. hash this string

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hashedString = Hash(attributesbla blafmi_pathxyz)
So basically the key will be
key = "597f86cd-13f3-44c0-bece-a1e77ba43228.f645ad92-e38d-4d1a-b510-d1b09a74a8ca-login.microsoftonline.com-token-4b0db8c2-9f26-4417-8bde-3f0e3656f8e0-{hashedString}"

Update the feedback
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants