Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/google_identity_services_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.2.1

* Relaxes the `renderButton` API so any JS-Interop Object can be its `target`.
* Exposes the `Button*` configuration enums, so the rendered button can be configured.

## 0.2.0

* Adds `renderButton` API to `id.dart`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:google_identity_services_web/id.dart';
import 'package:integration_test/integration_test.dart';
import 'package:js/js.dart';

import 'src/dom.dart';
import 'utils.dart' as utils;

void main() async {
Expand All @@ -19,6 +20,17 @@ void main() async {
await utils.installGisMock();
});

group('renderButton', () {
testWidgets('supports a js-interop target from any library', (_) async {
final DomElement target = createDomElement('div');

id.renderButton(target);

final DomElement? button = target.querySelector('button');
expect(button, isNotNull);
});
});

group('prompt', () {
testWidgets('supports a moment notification callback', (_) async {
id.initialize(IdConfiguration(client_id: 'testing_1-2-3'));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'package:js/js.dart';
import 'package:js/js_util.dart' as js_util;

@JS()
@staticInterop
class DomDocument {}

extension DomDocumentExtension on DomDocument {
DomElement createElement(String name, [Object? options]) =>
js_util.callMethod(this, 'createElement',
<Object>[name, if (options != null) options]) as DomElement;
}

@JS()
@staticInterop
class DomElement {}

extension DomElementExtension on DomElement {
external DomElement? querySelector(String selector);
}

@JS('document')
external DomDocument get domDocument;

DomElement createDomElement(String tag) => domDocument.createElement(tag);
5 changes: 3 additions & 2 deletions packages/google_identity_services_web/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import 'package:google_identity_services_web/id.dart';
import 'package:google_identity_services_web/loader.dart' as gis;
// #enddocregion use-loader
import 'package:js/js.dart' show allowInterop;
import 'package:jwt_decoder/jwt_decoder.dart' as jwt;

import 'src/jwt.dart' as jwt;

// #docregion use-loader
void main() async {
Expand All @@ -32,7 +33,7 @@ void main() async {
/// Handles the ID token returned from the One Tap prompt.
/// See: https://developers.google.com/identity/gsi/web/reference/js-reference#callback
void onCredentialResponse(CredentialResponse o) {
final Map<String, dynamic>? payload = jwt.JwtDecoder.tryDecode(o.credential!);
final Map<String, dynamic>? payload = jwt.decodePayload(o.credential);
if (payload != null) {
print('Hello, ${payload["name"]}');
print(o.select_by);
Expand Down
50 changes: 50 additions & 0 deletions packages/google_identity_services_web/example/lib/src/jwt.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert';

/// A codec that can encode/decode JWT payloads.
///
/// See https://www.rfc-editor.org/rfc/rfc7519#section-3
final Codec<Object?, String> _jwtCodec = json.fuse(utf8).fuse(base64);

/// A RegExp that can match, and extract parts from a JWT Token.
///
/// A JWT token consists of 3 base-64 encoded parts of data separated by periods:
///
/// header.payload.signature
///
/// More info: https://regexr.com/789qc
final RegExp _jwtTokenRegexp = RegExp(
r'^(?<header>[^\.\s]+)\.(?<payload>[^\.\s]+)\.(?<signature>[^\.\s]+)$');

/// Decodes the `claims` of a JWT token and returns them as a Map.
///
/// JWT `claims` are stored as a JSON object in the `payload` part of the token.
///
/// (This method does not validate the signature of the token.)
///
/// See https://www.rfc-editor.org/rfc/rfc7519#section-3
Map<String, Object?>? decodePayload(String? token) {
if (token != null) {
final RegExpMatch? match = _jwtTokenRegexp.firstMatch(token);
if (match != null) {
return _decodeJwtPayload(match.namedGroup('payload'));
}
}

return null;
}

/// Decodes a JWT payload using the [_jwtCodec].
Map<String, Object?>? _decodeJwtPayload(String? payload) {
try {
// Payload must be normalized before passing it to the codec
return _jwtCodec.decode(base64.normalize(payload!))
as Map<String, Object?>?;
} catch (_) {
// Do nothing, we always return null for any failure.
}
return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ dependencies:
path: ../
http: ^0.13.5
js: ^0.6.4
jwt_decoder: 2.0.1

dev_dependencies:
build_runner: ^2.1.10 # To extract README excerpts only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ class Id {
initialize(config) {
this.config = config;
}
renderButton(target, config) {
// Simulate rendering a button.
target.replaceChildren();
target.dataset.buttonConfig = config;
let button = document.createElement('button');
target.append(button);
}
prompt(momentListener) {
callAsync(() => {
if (this.mockCredentialResponse) {
Expand Down
7 changes: 7 additions & 0 deletions packages/google_identity_services_web/lib/id.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
export 'src/js_interop/google_accounts_id.dart';
export 'src/js_interop/shared.dart'
show
ButtonLogoAlignment,
ButtonShape,
ButtonSize,
ButtonText,
ButtonTheme,
ButtonType,
CredentialSelectBy,
GoogleIdentityServicesErrorType,
MomentDismissedReason,
MomentNotDisplayedReason,
MomentSkippedReason,
Expand Down
3 changes: 2 additions & 1 deletion packages/google_identity_services_web/lib/oauth2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
// found in the LICENSE file.

export 'src/js_interop/google_accounts_oauth2.dart';
export 'src/js_interop/shared.dart' show UxMode;
export 'src/js_interop/shared.dart'
show GoogleIdentityServicesErrorType, UxMode;
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ library google_accounts_id;

import 'package:js/js.dart';

import 'dom.dart';
import 'shared.dart';

/// Binding to the `google.accounts.id` JS global.
Expand Down Expand Up @@ -93,7 +92,7 @@ extension GoogleAccountsIdExtension on GoogleAccountsId {
/// Method: google.accounts.id.renderButton
/// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.renderButton
external void renderButton(
DomHtmlElement parent, [
Object parent, [
GsiButtonConfiguration options,
]);

Expand Down
2 changes: 1 addition & 1 deletion packages/google_identity_services_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: google_identity_services_web
description: A Dart JS-interop layer for Google Identity Services. Google's new sign-in SDK for Web that supports multiple types of credentials.
repository: https://github.com/flutter/packages/tree/main/packages/google_identity_services_web
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_identiy_services_web%22
version: 0.2.0
version: 0.2.1

environment:
sdk: ">=2.17.0 <4.0.0"
Expand Down
1 change: 0 additions & 1 deletion script/configs/allowed_pinned_deps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
# Legacy allowances, for dependencies that predate the tooling.
# TODO(stuartmorgan): Audit these. See
# https://github.com/flutter/flutter/issues/122713
- jwt_decoder
- lcov_parser
- adaptive_dialog
- provider
Expand Down