I'm attempting to access Microsoft Account oauth without any Azure AD accounts, but I am receiving an unauthorized_client error before the redirect back to my app.
Here is my yml configuration for spring security:
spring:
security:
oauth2:
client:
registration:
microsoft:
client-id: [my app registration client id]
client-secret: [my app registration secret id]
scope: profile, openid, https://graph.microsoft.com/User.Read
client-name: Microsoft
authorization-grant-type: authorization_code
provider: microsoft
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
provider:
microsoft:
authorization-uri: https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize
key-set-uri: https://login.microsoftonline.com/consumers/discovery/v2.0/keys
token-uri: https://login.microsoftonline.com/consumers/oauth2/v2.0/token
user-info-uri: https://graph.microsoft.com/oidc/userinfo
userNameAttribute: sub
issuer-uri: https://login.microsoftonline.com/${app.oauth2.tenant-id}/v2.0
app:
oauth2:
tenant-id: [my tenant id]
Client and secret ids match within both yml and azure portal. SSO fails both locally and when deployed. Is there any additional configuration I need to do here in order to get this working or do default Microsoft clients just not work whatsoever with java oauth?
There are actually several "features" in Microsoft's SSO implementation preventing OOTB functionality.
Resolution: Create a new scope under Expose an API. This scope can be named anything. Add this scope into your API Permissions section and update your scope property for the client registration to include the new scope.
More information on this issue can be found here: https://xsreality.medium.com/making-azure-ad-oidc-compliant-5734b70c43ff
Resolution: Don't include any of the graph api scopes. They currently do not work for Microsoft accounts (as of 2/16/21).
Resolution: Use the issuer that Microsoft is currently exposing under their well known endpoints api for whichever api you are using.
Consumer: https://login.microsoftonline.com/consumers/v2.0/.well-known/openid-configuration
Common: https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
I don't believe common will currently ever work since only consumer endpoints have a tenantId and that is included in the documented issuer string (as of 2/16/21), but the api has been in flux for the consumer endpoints with several different bugs. On 2/15/21, the issuer was hardcoded to "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0" regardless of tenantId and as documented in the above linked article, it was "https://sts.windows.net/407b9272-20f5-421c-a25f-e7a189309c4b/" as of 8/21/19. Currently (2/16/21), the issuer correctly includes the tenantId.
*** Update 2/18/21: despite the well-known endpoint saying the issuer accepts a tenant id, the issuer is still hard-coded to that tenantId I posted above.
spring:
security:
oauth2:
client:
registration:
microsoft:
client-id: [my app registration client id]
client-secret: [my app registration secret id]
scope: profile, openid, [my custom scope with the full api prefix]
client-name: Microsoft
authorization-grant-type: authorization_code
provider: microsoft
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
provider:
microsoft:
authorization-uri: https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize
key-set-uri: https://login.microsoftonline.com/consumers/discovery/v2.0/keys
token-uri: https://login.microsoftonline.com/consumers/oauth2/v2.0/token
user-info-uri: https://graph.microsoft.com/oidc/userinfo
userNameAttribute: sub
issuer-uri: https://login.microsoftonline.com/${app.oauth2.tenant-id}/v2.0
app:
oauth2:
tenant-id: [my tenant id]
For the value [my custom scope with the full api prefix], make sure to copy the full scope name including the api://[app id].