-
Notifications
You must be signed in to change notification settings - Fork 326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experimental API for OAuth 2.0 in WindowsAppSDK #3202
base: main-old
Are you sure you want to change the base?
Conversation
@@ -246,17 +246,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Framework.Widgets", "test\D | |||
EndProject | |||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependencyLifetimeManagerShadow", "dev\DynamicDependency\DynamicDependencyLifetimeManagerShadow\DynamicDependencyLifetimeManagerShadow.vcxproj", "{6539E9E1-BF36-40E5-86BC-070E99DB7B7B}" | |||
EndProject | |||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ToastNotificationTests", "test\ToastNotificationTests\ToastNotificationTests.vcxproj", "{E977B1BD-00DC-4085-A105-E0A18E0183D7}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This project seems to be mostly deleted and was causing issues with VS trying to re-add it back in when building
Is there an API specification? |
My main issue with this approach is that it seems to require changes to Program.cs: This makes it hard for code to handle authentication in one place, and makes the life of libraries even harder, and you also need to provide this yourself instead of just relying on the auto-generated one. I'd encourage you to look at what .NET MAUI provides, with just a single-line of code to perform OAuth: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/communication/authentication?view=net-maui-7.0&tabs=windows#using-webauthenticator |
This will fail if another process is already using port 5000: https://github.com/ujjwalchadha/OAuthConsumptionSample/blob/014a70ef4dd02d623e95bb01c91ee6689b406d0b/OAuthConsumptionSample/GoogleOAuthPage.xaml.cs#L169 |
Nothing here (yet). The sample was intended to be somewhat of a "how to," though the code paths there might not be representative enough to capture enough usage scenarios. I've copied some sample code that hopefully give a better sense of how the API is used (though it still lacks examples for other grant types such as client credentials, but that's probably for the best). |
Three-ish issues here:
There was a suggestion to make this slightly simpler: change/add an overload that accepts the event args object, though this would only save on the need to QI.
The problem there, and the problem that heavily shaped the API here (and likely the reason that API is documented as non-functional on Windows) is that Windows and WindowsAppSDK lack key features that allow such a design to work. To list just a few things:
The "best" we could probably do is to have a local server running that handles a number of these, but it's not without tradeoffs. The PR description covers a good chunk of this. |
In MicrosoftEdge/WebView2Feedback#1647, commented below:
Is this API is for short-term? Or was the plan for longer term changed? |
While I lack the context on that issue/conversation, it does link back to #441 in the following sentence, and that plan has been changed, as noted in the description that you quote. As far as WindowsAppSDK is concerned (or at least the current POR), there are no plans to port/open-source WAB, so it will remain UWP only. |
That is only single line in code. On all platforms other than windows, other setup are required, e.g. adding init code (android) or interceptor code in corresponding callback (ios). Each platform also needs to (rightfully) defines protocols schema, or even additional activities (android). At least this is the case for the web authenticator of Xamarin, MAUI's predecessor. Maybe MAUI has some other tricks up its sleeves to reduce setup steps required, but I think the API introduced in this PR is on the right trick for a general-purpose API that can be consumed by e.g. WPF, MFC or even console app (think git credential manager). I'd also like WinUI 3 apps to have a nicer API, though. Maybe additional integration with WinUI 3 that builds on top of the API here can be provided as another package:
|
@dunhor whats the latest up date on this? |
Spec dropped #4772 |
Before continuing, I would advise you to familiarize yourself with the following RFCs:
There are other RFCs that are relevant for OAuth 2.0, but these are probably the most important in terms of understanding the design here.
This prototype is developed enough to the point where it has a fully functional implementation with tests, is free from any known bugs, and has preliminary functional samples. We've done a preliminary review of the design in general, but no formal API review has been done yet, so names, usage patterns, etc. are likely to change. We are opening this PR semi-early as a request for feedback and suggestions.
The samples can be found here, although some work will be necessary to get them to run since the API is not currently present in WindowsAppSDK: https://github.com/ujjwalchadha/OAuthConsumptionSample
Why
OAuth seems to be a common ask for Windows App SDK applications. UWP has the WebAuthenticationBroker class, however that API is not usable by non-UWP applications. One option was to port that API and modify it to work for non-UWP applications, however the code owners opted not to pursue that option. Therefore, we are taking a separate approach. As a result, we've opted to follow OAuth best practices more closely - e.g. using user's default browser - and the end design is dramatically different than WebAuthenticationBroker, more closely resembling other APIs such as AppAuth.
Design Overview
The API opts to give more "raw" control over the use of OAuth. E.g. it has built-in helpers for all grant types in the OAuth spec as well as enough flexibility to use custom/extension values. This includes things like splitting authorization code requests into two parts. The API also uses best practices by default - such as PKCE - but does not mandate it. The only requirement imposed is the use of a
state
value in authorization code requests (which is required by the OAuth spec), and it requires that this value is globally unique across all authorization requests in the system since the state value is used to coordinate IPC. This only affects applications manually specifyingstate
values as the API will generate one that's guaranteed to be unique if none is provided.With the API, there's effectively three operations:
1 & 2 are effectively the same operation, depending on how you think about it. They are separate out of necessity because the application needs to handle the redirect, either through a localhost server or through protocol activation (more on this below). 2 will take care of any necessary IPC if the redirect comes in a different process (protocol activation). 3 is effectively just a POST request and provided mostly out of convenience (although I doubt its usefulness as most consumers should be using client credentials, which should never be present on a user's machine).
The request/response types all have properties that map 1:1 (with the exception of PKCE) with their counterparts in the OAuth standard. A map of key/value pairs is provided for specifying arguments outside the OAuth specification. The type of each argument is selected to avoid errors as much as possible. E.g.
expires_in
could arguably be represented as aDateTime
, however for now is aString
in an implicit grant type response since it is extracted from the response URI, and aDouble
in the token response since it comes out of the parsed JSON.Redirection
To start out, we are not taking a stance on which redirection "scheme" the application should use: either localhost redirect or protocol activation. Both have their pros and cons
We had discussed embedding a web server into the API, but opted - at least for now - against it for a few reasons:
Security Considerations
RFC 6819 describes the general OAuth 2.0 threat model and has some good information in there. RFC 8252 also has some good info that's specific to native applications. Therefore, I won't exhaustively cover everything here; only what's specific to this API. The most obvious attack surface that is unique to this API is the fact that we may need to perform IPC to communicate the authorization code back to the requesting process. A combination of client secrets, PKCE, and encryption are used/recommended to avoid potential issues.
Scenario 1: "Intercepting" Communication
A
initiates an auth requestB
sees this (e.g. by listening to named port creation) and terminatesA
C
gets protocol activated and sends the auth code toB
Remediations:
B
does not knowB
does not know the original code verifierB
does not have access to the client secretScenario 2: Sending Bad Data
A
initiates an auth requestB
sees this and sends its own authorization code toA
Remediations:
B
is unable to encrypt the data it's sending because it does not know the original stateB
to obtain the false codeScenario 3: Bad Initiator
A
initiates an auth requestB
gets protocol activated and sends the authorization code toA
Remediations:
B
does not have access to the client secretNote that this problem is unavoidable no matter what. The alternative might be to use localhost for the redirect URI so that the response comes in-proc, however localhost URIs are not specific to any one application, so an attacker could control the entire flow.
Example Code
Some example code for performing some tasks
Performing an Authorization Code Request
Exchanging an Authorization Code for an Access Token
Refreshing an Access Token
Completing an Authorization Request from a Protocol Activation