Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Flutter multiplatform login by Ashley Manraj

GDG Montreal
November 14, 2024
5

Flutter multiplatform login by Ashley Manraj

Login flow are usually thought out as separate integrations between mobile Oauth2 integrations and browser based redirect integrations for login. Ory Kratos published in 2024 their new single sign-in on flow using either the native mobile or a new web flow for single page application.

So we decided at Pvotal to create a library and cross platform implementation to completely offload this problem for login systems leveraging Flutter. It handles OpenID with google and consent, passkey, password or recovery key.

We want to provide in this presentation the base bloc structure and key considerations to allow other developers to get inspired by this method to integrate similarly with their authentication providers. We want to also present the routes post-authentication to change one user's configurations dynamically depending on what was configured in their profile leveraging the UI node system of Ory Kratos.

https://youtu.be/1GXp15eIAgg

DevFest Montreal 2024

GDG Montreal

November 14, 2024
Tweet

More Decks by GDG Montreal

Transcript

  1. I. Who Am I • Who am I introduction •

    Open source doing the heavy lifting • Infrastream per project template II. From server based Go templates to Flutter implementation • Former Go login implementation • Flutter Ory Node UI architecture for Web and Mobile • Ory Passkey Strategy III. Flutter code exploration • Authentication repository (Demo) • BLoC structure and content (Demo) IV. Core concepts Node UI Flutter • Traits mapping • UI message structure • UI node structure - script Table of Contents
  2. are Who am I • Former applicative pentester • Former

    banking security reviewer • Current Pvotal Technologies Chief Technology officer • Focused on building Pvotal Infrastream ◦ Our Company Platform Engineering solution Infrastream, will be self-instantiable directly from the Infrastream website allowing organizations to standardize infrastructure management expected publicly for Q2 2025. ◦ This enables Pvotal to deliver integrated, cloud-native management tailored for Google Cloud Platform (GCP). As an infrastructure-as-code solution with Continuous Integration and Continuous Deployment, our platform uses opinionated configuration manifests to orchestrate every aspect of a managed Google Cloud organization, ensuring seamless delivery from the source code repository to container deployment without third parties Software as a Service. ◦ By embracing this innovative approach, Pvotal eliminates reliance on error-prone infrastructure scripts, providing a robust, actionable baseline that delivers immediate value with minimal consulting as most security concerns are managed by Pvotal from your manifests to radically simplify security configurations. Our solution also supports long-term maintenance of entire projects lifecycles with GCE, GKE with managed service mesh and Cloud Run.
  3. are Local code review Within presenter laptop unified flutter library

    • Local repositories code review • Local providers code review • Significant BloC code review
  4. are Traits mapping Every social sign-in provider returns different data

    in their payloads. Some providers use usernames, others emails, and so on. While you might expect to get some basic information consistently, the payload isn't standardized. As a result, when integrating with social sign-in providers, you must specify how to map the data you get from the specific provider to the Identity traits. You define this mapping by creating a Jsonnet code snippet. This snippet becomes a part of the Ory Identities configuration for the given social sign-in provider. local claims = std.extVar('claims'); { identity: { traits: { email: claims.email }, metadata_public: { discord_username: claims.discord_username, }, metadata_admin: { // ... }, } }
  5. are Traits mapping - Github full example github.data-mapper.jsonnet : local

    claims = { email_verified: false, } + std.extVar('claims'); { identity: { traits: { // Allowing unverified email addresses enables account // enumeration attacks, especially if the value is used for // e.g. verification or as a password login identifier. // Therefore we only return the email if it (a) exists and (b) is marked verified by GitHub. [if 'email' in claims && claims.email_verified then 'email' else null]: claims.email, }, metadata_public: { github_username: claims.username, } }, } JsonNet data mapper returns : { "identity": { "traits": { "email": "[email protected]" }, "metadata_public": { "github_username": "a-manraj-pvotal" } } } # This is the YAML representation of an identity id: "5f425c8d-7ffc-4768-8f23-7647a74fdf13" credentials: oidc: id: oidc identifiers: - example:some-identity-id-4hA8gk config: - provider: example identifier: some-identity-id-4hA8gk schema_id: some-example traits: email: [email protected] metadata_public: github_username: a-manraj-pvotal
  6. are UI node structure { id: "9b527900-2199-4221-9252-7971b3362282", type: "browser", expires_at:

    "2021-04-28T13:55:36.046466067Z", issued_at: "2021-04-28T12:55:36.046466067Z", ui: { action: "https://playground.projects.oryapis.com/self-service/settings?flow=9b527900-2199-4221-9252-7971b3362282", method: "POST", nodes: [ { type: "input", group: "default", attributes: { node_type: "input", name: "csrf_token", type: "hidden", value: "U3r/lgEfT8rA1Lg0Eeo06oGO8mX6T4TKoe/z7rbInhvYeacbRg0IW9zrqnpU1wmQJXKiekNzdLnypx5naHXoPg==", required: true, disabled: false, }, messages: null, meta: {}, }, { type: "input", group: "profile", attributes: { node_type: "input", name: "traits.email", type: "email", value: "[email protected]", disabled: false, }, messages: null, meta: { label: { id: 1070002, text: "E-Mail", type: "info", }, Nodes are grouped (using the group key) based on the source that generated the node. Sources are the different methods such as "password" ("Sign in/up with ID & password"), "oidc" (Social Sign In), "link" (Password reset and email verification), "profile" ("Update your profile") and the "default" group which typically contains the mandatory CSRF token for web.
  7. are UI node structure - message Ory Identities helps users

    understand what is happening by providing messages that explain what went wrong or what needs to be done. Examples are "The provided credentials are invalid", "Missing property email" and similar. Typically login, registration, settings, ... flows include such messages on different levels: At the root level, indicating that the message affects the whole request (e.g. request expired) At the method (password, oidc, profile) level, indicating that the message affects a specific method / form. At the field level, indicating that the message affects a form field (e.g. validation errors). The message ID is a 7-digit number (xyyzzzz) where x is the message type which is either 1 for an info message (e.g. 1020000), 4 (e.g. 4020000) for an input validation error message, and 5 (e.g. 5020000) for a generic error message. yy is the module or flow this error references and can be: 01 for login messages (e.g. 1010000) 02 for logout messages (e.g. 1020000) 03 for multi-factor authentication messages (e.g. 1030000) 04 for registration messages (e.g. 1040000) 05 for settings messages (e.g. 1050000) 06 for account recovery messages (e.g. 1060000) 07 for email/phone verification messages (e.g. 1070000) zzzz is the message ID and typically starts at 0001. For example, message ID 4070001 (4 for input validation error, 07 for verification, 0001 for the concrete message) is: The verification code has expired or was otherwise invalid. Please request another code..
  8. are UI node structure - script { "type": "script", "group":

    "webauthn", "attributes": { "src": "http://localhost:4455/.well-known/ory/webauthn.js", "async": true, "referrerpolicy": "no-referrer", "crossorigin": "anonymous", "integrity": "sha512-E3ctShTQEYTkfWrjztRCbP77lN7L0jJC2IOd6j8vqUKslvqhX/H o3QxlQJIeTI78krzAWUQlDXd9JQ0PZlKhzQ==", "type": "text/javascript", "id": "webauthn_script", "node_type": "script" }, This script would need to be dynamically evaluated within the web context even in flutter specifically for the script node type. Luckily those values are controlled and escaped by the Kratos engine. CSPv3 headers could be included to harden all the script references referenced by the source (src) to be loaded.
  9. are Conclusion Advantages: • Removes need for a custom login

    server per client (Outside custom consent and configuration Ory Kratos and Hydra maintained by Ory) • Template and customize flutter UI per client from same maintained parent code implementation. Allows for internationalization, images and video part of the customized login per client Current issues: • Dynamic javascript evaluation in web (eval) to load the passkey javascript implementation which affects the clients if compromised compared to Go templated potentially affecting the backend engines • Need standardization for infrastructure as code proxies between Kratos and Hydra to manage efficiently multiple Kratos to a common infrastructure maintained Hydra Oauth2 engine. In terms of zero trust, we want to protect that common hydra from malicious admin operations from any single one not to affect the other clients.