Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
OAuth2Manager w Windows App SDK umożliwia aplikacjom stacjonarnym, takim jak WinUI 3 bezproblemowe wykonywanie autoryzacji OAuth 2.0 w systemie Windows. API OAuth2Manager nie udostępnia API dla implicitnych żądań i poświadczeń hasła właściciela zasobu ze względu na względy bezpieczeństwa. Użyj typu przyznania kodu autoryzacji z kluczem weryfikującym do wymiany kodu (PKCE). Aby uzyskać więcej informacji, zobacz PKCE RFC.
Tło OAuth 2.0 dla aplikacji systemu Windows
Windows Runtime (WinRT) WebAuthenticationBroker, przeznaczony głównie dla aplikacji platformy UWP, stanowi pewne wyzwania podczas użycia w aplikacjach desktopowych. Kluczowe problemy obejmują zależność od ApplicationView, która nie jest zgodna z frameworkami do aplikacji desktopowych. W rezultacie deweloperzy muszą uciekać się do obejść z użyciem interfejsów międzyoperacyjności i dodatkowego kodu w celu zaimplementowania funkcji OAuth 2.0 w WinUI i innych aplikacjach desktopowych.
Interfejs API OAuth2Manager w Windows App SDK
Interfejs API OAuth2Manager dla Windows App SDK zapewnia usprawnione rozwiązanie spełniające oczekiwania deweloperów. Oferuje ona bezproblemowe funkcje protokołu OAuth 2.0 z pełną parzystością funkcji na wszystkich platformach systemu Windows obsługiwanych przez Windows App SDK. Nowy interfejs API eliminuje potrzebę kłopotliwych obejść i upraszcza proces dołączania funkcji OAuth 2.0 do aplikacji klasycznych.
Element OAuth2Manager różni się od elementu WebAuthenticationBroker w środowisku WinRT. Jest to bardziej zgodne z najlepszymi rozwiązaniami protokołu OAuth 2.0 — na przykład przy użyciu domyślnej przeglądarki użytkownika. Najlepsze rozwiązania dotyczące interfejsu API pochodzą z IETF (Internet Engineering Task Force) OAuth 2.0 Authorization Framework RFC 6749, PKCE RFC 7636 i OAuth 2.0 for Native Apps RFC 8252.
Przykłady kodu OAuth 2.0
Pełna przykładowa aplikacja WinUI jest dostępna w GitHub. Poniższe sekcje zawierają fragmenty kodu dla najbardziej typowych przepływów protokołu OAuth 2.0 przy użyciu interfejsu API OAuth2Manager.
Żądanie kodu autoryzacji
W poniższym przykładzie pokazano, jak wykonać żądanie kodu autoryzacji przy użyciu OAuth2Manager w Windows App SDK:
// Get the WindowId for the application window
Microsoft::UI::WindowId parentWindowId = this->AppWindow().Id();
AuthRequestParams authRequestParams = AuthRequestParams::CreateForAuthorizationCodeRequest(L"my_client_id",
Uri(L"my-app:/oauth-callback/"));
authRequestParams.Scope(L"user:email user:birthday");
AuthRequestResult authRequestResult = co_await OAuth2Manager::RequestAuthWithParamsAsync(parentWindowId,
Uri(L"https://my.server.com/oauth/authorize"), authRequestParams);
if (AuthResponse authResponse = authRequestResult.Response())
{
//To obtain the authorization code
//authResponse.Code();
//To obtain the access token
DoTokenExchange(authResponse);
}
else
{
AuthFailure authFailure = authRequestResult.Failure();
NotifyFailure(authFailure.Error(), authFailure.ErrorDescription());
}
Wymień kod autoryzacji na token dostępu
W poniższym przykładzie pokazano, jak wymienić kod autoryzacji na token dostępu przy użyciu OAuth2Manager.
W przypadku klientów publicznych, takich jak natywne aplikacje klasyczne, korzystających z PKCE, nie dołączaj tajnego hasła klienta. Zamiast tego, weryfikator kodu PKCE zapewnia zabezpieczenia.
AuthResponse authResponse = authRequestResult.Response();
TokenRequestParams tokenRequestParams = TokenRequestParams::CreateForAuthorizationCodeRequest(authResponse);
// For public clients using PKCE, do not include ClientAuthentication
TokenRequestResult tokenRequestResult = co_await OAuth2Manager::RequestTokenAsync(
Uri(L"https://my.server.com/oauth/token"), tokenRequestParams);
if (TokenResponse tokenResponse = tokenRequestResult.Response())
{
String accessToken = tokenResponse.AccessToken();
String tokenType = tokenResponse.TokenType();
// RefreshToken string null/empty when not present
if (String refreshToken = tokenResponse.RefreshToken(); !refreshToken.empty())
{
// ExpiresIn is zero when not present
DateTime expires = winrt::clock::now();
if (String expiresIn = tokenResponse.ExpiresIn(); std::stoi(expiresIn) != 0)
{
expires += std::chrono::seconds(static_cast<int64_t>(std::stoi(expiresIn)));
}
else
{
// Assume a duration of one hour
expires += std::chrono::hours(1);
}
//Schedule a refresh of the access token
myAppState.ScheduleRefreshAt(expires, refreshToken);
}
// Use the access token for resources
DoRequestWithToken(accessToken, tokenType);
}
else
{
TokenFailure tokenFailure = tokenRequestResult.Failure();
NotifyFailure(tokenFailure.Error(), tokenFailure.ErrorDescription());
}
W przypadku klientów poufnych (takich jak aplikacje internetowe lub usługi), które mają tajny klucz klienta, dołącz parametr ClientAuthentication:
AuthResponse authResponse = authRequestResult.Response();
TokenRequestParams tokenRequestParams = TokenRequestParams::CreateForAuthorizationCodeRequest(authResponse);
ClientAuthentication clientAuth = ClientAuthentication::CreateForBasicAuthorization(L"my_client_id",
L"my_client_secret");
TokenRequestResult tokenRequestResult = co_await OAuth2Manager::RequestTokenAsync(
Uri(L"https://my.server.com/oauth/token"), tokenRequestParams, clientAuth);
// Handle the response as shown in the previous example
Odśwież token dostępu
W poniższym przykładzie pokazano, jak odświeżyć token dostępu przy użyciu metody OAuth2Manager's RefreshTokenAsync.
W przypadku klientów publicznych korzystających z PKCE pomiń ClientAuthentication parametr :
TokenRequestParams tokenRequestParams = TokenRequestParams::CreateForRefreshToken(refreshToken);
// For public clients using PKCE, do not include ClientAuthentication
TokenRequestResult tokenRequestResult = co_await OAuth2Manager::RequestTokenAsync(
Uri(L"https://my.server.com/oauth/token"), tokenRequestParams);
if (TokenResponse tokenResponse = tokenRequestResult.Response())
{
UpdateToken(tokenResponse.AccessToken(), tokenResponse.TokenType(), tokenResponse.ExpiresIn());
//Store new refresh token if present
if (String refreshToken = tokenResponse.RefreshToken(); !refreshToken.empty())
{
// ExpiresIn is zero when not present
DateTime expires = winrt::clock::now();
if (String expiresInStr = tokenResponse.ExpiresIn(); !expiresInStr.empty())
{
int expiresIn = std::stoi(expiresInStr);
if (expiresIn != 0)
{
expires += std::chrono::seconds(static_cast<int64_t>(expiresIn));
}
}
else
{
// Assume a duration of one hour
expires += std::chrono::hours(1);
}
//Schedule a refresh of the access token
myAppState.ScheduleRefreshAt(expires, refreshToken);
}
}
else
{
TokenFailure tokenFailure = tokenRequestResult.Failure();
NotifyFailure(tokenFailure.Error(), tokenFailure.ErrorDescription());
}
W przypadku poufnych klientów, którzy mają tajny klucz klienta, dołącz parametr ClientAuthentication.
TokenRequestParams tokenRequestParams = TokenRequestParams::CreateForRefreshToken(refreshToken);
ClientAuthentication clientAuth = ClientAuthentication::CreateForBasicAuthorization(L"my_client_id",
L"my_client_secret");
TokenRequestResult tokenRequestResult = co_await OAuth2Manager::RequestTokenAsync(
Uri(L"https://my.server.com/oauth/token"), tokenRequestParams, clientAuth);
// Handle the response as shown in the previous example
Ukończ żądanie autoryzacji
Aby ukończyć żądanie autoryzacji z aktywacji protokołu, aplikacja powinna obsługiwać zdarzenie AppInstance.Activated . To zdarzenie jest wymagane, gdy aplikacja ma niestandardową logikę przekierowania. Pełny przykład jest dostępny w GitHub.
Użyj następującego kodu:
void App::OnActivated(const IActivatedEventArgs& args)
{
if (args.Kind() == ActivationKind::Protocol)
{
auto protocolArgs = args.as<ProtocolActivatedEventArgs>();
if (OAuth2Manager::CompleteAuthRequest(protocolArgs.Uri()))
{
TerminateCurrentProcess();
}
DisplayUnhandledMessageToUser();
}
}