android - 在哪里可以找到OAuth2.0的标识符和 secret , 'imaginary functions'是什么意思?

标签 android dart flutter oauth-2.0

我正在遵循这个documentation在我的flutter应用程序中实现OAuth2.0,并且不了解一些事情,这是文档中的代码:

import 'dart:io';
import 'package:oauth2/oauth2.dart' as oauth2;

// These URLs are endpoints that are provided by the authorization
// server. They're usually included in the server's documentation of its
// OAuth2 API.
final authorizationEndpoint =
    Uri.parse("http://example.com/oauth2/authorization");
final tokenEndpoint =
    Uri.parse("http://example.com/oauth2/token");

// The authorization server will issue each client a separate client
// identifier and secret, which allows the server to tell which client
// is accessing it. Some servers may also have an anonymous
// identifier/secret pair that any client may use.
//
// Note that clients whose source code or binary executable is readily
// available may not be able to make sure the client secret is kept a
// secret. This is fine; OAuth2 servers generally won't rely on knowing
// with certainty that a client is who it claims to be.
final identifier = "my client identifier";
final secret = "my client secret";

// This is a URL on your application's server. The authorization server
// will redirect the resource owner here once they've authorized the
// client. The redirection will include the authorization code in the
// query parameters.
final redirectUrl = Uri.parse("http://my-site.com/oauth2-redirect");

/// A file in which the users credentials are stored persistently. If the server
/// issues a refresh token allowing the client to refresh outdated credentials,
/// these may be valid indefinitely, meaning the user never has to
/// re-authenticate.
final credentialsFile = new File("~/.myapp/credentials.json");

/// Either load an OAuth2 client from saved credentials or authenticate a new
/// one.
Future<oauth2.Client> getClient() async {
  var exists = await credentialsFile.exists();

  // If the OAuth2 credentials have already been saved from a previous run, we
  // just want to reload them.
  if (exists) {
    var credentials = new oauth2.Credentials.fromJson(
        await credentialsFile.readAsString());
    return new oauth2.Client(credentials,
        identifier: identifier, secret: secret);
  }

  // If we don't have OAuth2 credentials yet, we need to get the resource owner
  // to authorize us. We're assuming here that we're a command-line application.
  var grant = new oauth2.AuthorizationCodeGrant(
      identifier, authorizationEndpoint, tokenEndpoint,
      secret: secret);

  // Redirect the resource owner to the authorization URL. This will be a URL on
  // the authorization server (authorizationEndpoint with some additional query
  // parameters). Once the resource owner has authorized, they'll be redirected
  // to `redirectUrl` with an authorization code.
  //
  // `redirect` is an imaginary function that redirects the resource
  // owner's browser.
  await redirect(grant.getAuthorizationUrl(redirectUrl));

  // Another imaginary function that listens for a request to `redirectUrl`.
  var request = await listen(redirectUrl);

  // Once the user is redirected to `redirectUrl`, pass the query parameters to
  // the AuthorizationCodeGrant. It will validate them and extract the
  // authorization code to create a new Client.
  return await grant.handleAuthorizationResponse(request.uri.queryParameters);
}

main() async {
  var client = await loadClient();

  // Once you have a Client, you can use it just like any other HTTP client.
  var result = client.read("http://example.com/protected-resources.txt");

  // Once we're done with the client, save the credentials file. This ensures
  // that if the credentials were automatically refreshed while using the
  // client, the new credentials are available for the next run of the
  // program.
  await credentialsFile.writeAsString(client.credentials.toJson());

  print(result);
}

在哪里可以找到标识符和 secret ?它显示在/.well-known/openid-configuration页面中吗?另外,我如何实现这些功能:

await redirect(grant.getAuthorizationUrl(redirectUrl));
var request = await listen(redirectUrl);
var client = await loadClient();

文档中提到它是一种虚函数。如何实现这些功能?

enter image description here

最佳答案

带有抖动的OAuth永远不会在Android或iOS上完全简单明了,因为它与OS缺乏深度集成,因此您必须对每个OS进行一些配置。老实说,在本机Android / iOS中也不是那么容易。
而且您正在查看的该插件似乎更侧重于服务器应用程序,这就是为什么它对于开发者而言并不完全有意义。但是,并非不可能!
启用OAuth的主要功能是使用自定义网址方案或通用链接。自定义网址方案类似于com.myapp.customurlscheme://-用于代替“https”。通用链接使用https和一个网站,即https://myapp.com/customurl/。一个重要的区别是,要使用通用链接,您必须控制该网站并上传一个文件,Apple可以检查该文件以了解您是否已授予该应用程序替换该网站或网站部分的权限。如果用户已安装该应用程序,则在转到该URL时将显示该应用程序。如果没有,他们会在网站上显示一些信息(通常是安装该应用程序的链接)。
如果您是使用OAuth进行身份验证的客户端,则通常不希望复制网站的一部分,因为您所做的只是创建回调(重定向)URL,因此您可能会使用自定义网址方案。这必须通过添加到您的AndroidManifest.xml或Info.plist文件中来完成。
对于iOS的Info.plist来说,类似于:

  <key>CFBundleURLTypes</key>
  <array>
    <dict>
      <key>CFBundleTypeRole</key>
      <string>Editor</string>
      <key>CFBundleURLName</key>
      <string>[ANY_URL_NAME]</string>
      <key>CFBundleURLSchemes</key>
      <array>
        <string>[YOUR_SCHEME]</string>
      </array>
    </dict>
  </array>
对于AndroidManifest.xml,类似:
    <activity>
       
      ...
   
      <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
          android:scheme="[YOUR_SCHEME]"
          android:host="[YOUR_HOST]" />
      </intent-filter>
设置完成后,您可以使用这些自定义网址之一在本地“打开”应用程序时本地添加侦听器。有点痛苦,但值得庆幸的是,有人制作了一个可以提供帮助的插件:Universal Links(并为他们提供了上面的示例配置,因为我从他们的文档中偷偷偷了了它)。您可以在主要功能(或类似功能)中使用其getInitialLink()方法和/或获取链接流,以使用getLinksStream()进行监听。我认为第二个是您将要使用的,因为启动OAuth / OpenID工作流程时该应用程序已经打开-因此您可以在打开应用程序后立即开始监听,也可以在开始使用OAuth之前立即开始监听 call 。
好的,这很多。不过,这是有原因的-这样做为您的应用提供了一种从浏览器或其他应用接收重定向的方式。因此,如果处理该getLinksStream,则可以或多或少地从oauth2服务器接收回调。您可以设置一些系统,在其中创建将来,以等待特定链接通过链接流传递。
这样覆盖

// Another imaginary function that listens for a request to 'redirectUrl'.

var request = await listen(redirectUrl);


现在我们需要对第一个imaginary function进行处理。在应用程序案例中,这根本不是想象中的-您需要启动该URL,而不是像在服务器上那样使页面重定向。有一个插件:Url Launcher
所以说await redirect(grant.getAuthorizationUrl(redirectUrl));时,您实际上要执行的操作是使用url_launcher的grant.getAuthorizationUrl(带有适当的标志来启动launch()),必须通过测试来确定。您可能要强制使用浏览器,这取决于是否使用浏览器。 OAuth服务器上有一个可以处理身份验证的应用。如果可以,您可能希望在其应用中打开该网址,以便该用户已经登录)。
这个难题还需要解决很多其他问题。第一个是您必须传递给redirectUrlgetAuthorizationUrl。你问我在那放什么?!好吧,您使用我们之前设置的漂亮的自定义应用程序方案!因此,重定向网址将类似于com.myapp.customurlscheme:// customurlredirect。
因此,OAuth token 配置工作流程如下所示:
  • 您启动服务器
  • 的身份验证URL
  • 向用户显示登录页面,权限页面或服务器执行的任何操作
  • 一旦用户批准了请求,服务器就会将用户重定向回您的应用程序(它可能会问他们“您是否要在其中打开”或类似名称)。
  • 您的应用程序收到带有授权码
  • 的回调
  • 您的应用程序应使用该授权码来请求 token (我假设这由handleAuthorizationResponse处理)。

  • 现在,在实现所有这些之前,需要考虑一些事项。
  • 如果这是服务器应用程序,则您可能会有一个安全 secret ,可以向OAuth服务器证明您的应用程序是它声称的客户端。您可以从OAuth服务器获得并将其直接配置到服务器。但是,由于您正在编写应用程序,因此没有(简单)的方法来配置该安全 secret 。因此,应该使用带有PKCE且没有client_secret的OAuth授权代码流,而不是使用普通的OAuth。如果您觉得不对劲,则应该对PKCE进行一些阅读-Auth0具有good writeup。您正在使用的OAuth服务器也必须支持该功能,但是如果没有它,您的登录过程将是不安全的。
  • 与您通信的OAuth服务器必须了解并接受自定义url方案。大多数大公司都这样做,实际上它们具有与此类似的文档,应该可以引导您完成相同的过程(但不是特定于波动的)。实际上,它们实际上定义了自定义url方案应该是什么-在Facebook的情况下,如果您的应用程序ID为1234567,那么自定义url方案将类似于fb1234567://
  • 我没有对所使用的库进行过多研究,但您可能需要确保它实际上支持正确的OAuth工作流程。如果我怀疑它被设计为服务器端程序包,则可能不会。在这种情况下,您可能必须手动进行设置-实际上并不是那么困难,您只需要生成几个URL即可匹配OAuth服务器期望的URL,这些URL已被很好地记录和标准化。

  • 那是很多信息,但是不幸的是,OAuth2并不是那么简单(实际上,如果要执行其所需的工作,它就不可能那么简单)。祝您的应用程序好运!

    关于android - 在哪里可以找到OAuth2.0的标识符和 secret , 'imaginary functions'是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56166519/

    相关文章:

    android - 是否有机会在 GCM 中为两个不同的应用程序使用相同的 token ? [安卓]

    flutter - "This function has a return type of ' 小部件 ', but doesn' 以返回语句结束。”

    dart - 如何在小部件的子级中使用 "for"循环?

    flutter - Dart Generators:为什么我得到的 'LibraryDirectiveImpl'类型不是 'Statement'类型的子类型

    firebase - 如何在 Android Studio 中将 Firebase 添加到 Flutter Android 应用程序时将项目与 Gradle 文件同步(2020 年 4 月)

    java - Android ExpandableListView 填充了两次

    android - 如何修复IONIC V1构建Gradle过程

    android - 如何在 Android Studio 3.0 Canary 1 :Failed to resolve: com. google.android :android:2. 3.1 上解决此问题

    flutter - 如何查看应用发布版本的 Flutter 调试控制台输出?

    listview - 添加图像到列表 Flutter