Show portal user info

View on GitHub

Retrieve a user's details via a Portal.

Image of show portal user info

Use case

This portal information can be used to provide a customized UI experience for the user. For example, you can show a thumbnail next to their username in the header of an application to indicate that they are currently logged in. Additionally, apps such as Collector and Explorer use this functionality to integrate with Portal.

How to use the sample

When prompted, enter your ArcGIS Online credentials.

How it works

  1. An authentication challenge handler is set on ArcGISEnvironment.authenticationManager.
  2. A Portal is created, using PortalConnection.authenticated to require authentication.
  3. The portal is loaded, which triggers an authentication challenge.
  4. The ArcGISAuthenticationChallengeHandler callback is called to handle the authentication challenge.
  5. The OAuth login process is triggered using OAuthUserCredential.create().

If the portal is successfully loaded, the user property is used to populate a series of fields including:

  • fullName
  • username
  • email
  • thumbnail
  • userDescription
  • access

Similarly, the portalInfo property is used to populate:

  • organizationName
  • organizationDescription
  • thumbnail
  • canSearchPublic
  • canSharePublic

Relevant API

  • ArcGISAuthenticationChallengeHandler
  • AuthenticationManager
  • OAuthUserCredential
  • PortalInfo
  • PortalUser

About the data

This sample signs into your ArcGIS Online account and displays the user's profile information.

Tags

account, avatar, bio, cloud and portal, email, login, picture, profile, user, username

Sample Code

show_portal_user_info.dart
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import 'dart:typed_data';

import 'package:arcgis_maps/arcgis_maps.dart';
import 'package:flutter/material.dart';
import 'package:simple_html_css/simple_html_css.dart';

import '../../utils/sample_state_support.dart';

class ShowPortalUserInfo extends StatefulWidget {
  const ShowPortalUserInfo({super.key});

  @override
  State<ShowPortalUserInfo> createState() => _ShowPortalUserInfoState();
}

class _ShowPortalUserInfoState extends State<ShowPortalUserInfo>
    with SampleStateSupport
    implements ArcGISAuthenticationChallengeHandler {
  // Create an OAuthUserConfiguration.
  // This document describes the steps to configure OAuth for your app:
  // https://developers.arcgis.com/documentation/security-and-authentication/user-authentication/flows/authorization-code-with-pkce/
  final _oauthUserConfiguration = OAuthUserConfiguration(
    portalUri: Uri.parse('https://www.arcgis.com'),
    clientId: 'T0A3SudETrIQndd2',
    redirectUri: Uri.parse('my-ags-flutter-app://auth'),
  );
  // Create a Portal that requires authentication.
  final _portal =
      Portal.arcGISOnline(connection: PortalConnection.authenticated);
  // Create a Future that tracks the loading of the portal.
  Future<void>? _portalLoadFuture;
  // Create variables to store the user and organization thumbnails.
  Uint8List? _userThumbnail;
  Uint8List? _organizationThumbnail;

  @override
  void initState() {
    super.initState();

    // Set this class to the arcGISAuthenticationChallengeHandler property on the authentication manager.
    // This class implements the ArcGISAuthenticationChallengeHandler interface,
    // which allows it to handle authentication challenges via calls to its
    // handleArcGISAuthenticationChallenge() method.
    ArcGISEnvironment
        .authenticationManager.arcGISAuthenticationChallengeHandler = this;

    // Load the portal (which will trigger an authentication challenge), and then load the thumbnails.
    _portalLoadFuture = _portal.load().then((_) => loadThumbnails());
  }

  @override
  void dispose() async {
    // We do not want to handle authentication challenges outside of this sample,
    // so we remove this as the challenge handler.
    ArcGISEnvironment
        .authenticationManager.arcGISAuthenticationChallengeHandler = null;

    super.dispose();

    // Revoke OAuth tokens and remove all credentials to log out.
    await Future.wait(
      ArcGISEnvironment.authenticationManager.arcGISCredentialStore
          .getCredentials()
          .whereType<OAuthUserCredential>()
          .map((credential) => credential.revokeToken()),
    );
    ArcGISEnvironment.authenticationManager.arcGISCredentialStore.removeAll();
  }

  @override
  void handleArcGISAuthenticationChallenge(
    ArcGISAuthenticationChallenge challenge,
  ) async {
    try {
      // Initiate the sign in process to the OAuth server using the defined user configuration.
      final credential = await OAuthUserCredential.create(
        configuration: _oauthUserConfiguration,
      );

      // Sign in was successful, so continue with the provided credential.
      challenge.continueWithCredential(credential);
    } on ArcGISException catch (error) {
      // Sign in was canceled, or there was some other error.
      final e = (error.wrappedException as ArcGISException?) ?? error;
      if (e.errorType == ArcGISExceptionType.commonUserCanceled) {
        challenge.cancel();
      } else {
        challenge.continueAndFail();
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        minimum: const EdgeInsets.symmetric(horizontal: 10),
        // Create a FutureBuilder to respond to the loading of the portal.
        child: FutureBuilder(
          future: _portalLoadFuture,
          builder: (context, snapshot) {
            // If the portal is still loading, display a message.
            if (snapshot.connectionState != ConnectionState.done) {
              return const Text('Authenticating...');
            }

            // If the portal load failed with an error, display the error.
            if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            }

            // If the portal load succeeded, display the portal information.
            final titleStyle = Theme.of(context).textTheme.titleMedium;
            return SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '${_portal.user?.fullName} Profile',
                    style: Theme.of(context).textTheme.titleLarge,
                  ),
                  const SizedBox(height: 20.0),
                  _userThumbnail != null
                      ? Image.memory(_userThumbnail!)
                      : const Icon(Icons.person),
                  Text('Full name', style: titleStyle),
                  Text(_portal.user?.fullName ?? ''),
                  Text('Username', style: titleStyle),
                  Text(_portal.user?.username ?? ''),
                  Text('Email', style: titleStyle),
                  Text(_portal.user?.email ?? ''),
                  Text('Description', style: titleStyle),
                  Text(_portal.user?.userDescription ?? ''),
                  Text('Access', style: titleStyle),
                  Text(_portal.user?.access.name ?? ''),
                  const Divider(),
                  _organizationThumbnail != null
                      ? Image.memory(_organizationThumbnail!)
                      : const Icon(Icons.domain),
                  Text('Organization', style: titleStyle),
                  Text(_portal.portalInfo?.organizationName ?? ''),
                  Text('Can find external content', style: titleStyle),
                  Text('${_portal.portalInfo?.canSearchPublic}'),
                  Text('Can share items externally', style: titleStyle),
                  Text('${_portal.portalInfo?.canSharePublic}'),
                  Text('Description', style: titleStyle),
                  Padding(
                    padding: const EdgeInsets.only(left: 10.0),
                    child: RichText(
                      text: HTML.toTextSpan(
                        context,
                        _portal.portalInfo?.organizationDescription ?? '',
                      ),
                    ),
                  ),
                ],
              ),
            );
          },
        ),
      ),
    );
  }

  // Load the user and organization thumbnails.
  void loadThumbnails() {
    _portal.user?.thumbnail?.loadBytes().then((bytes) {
      setState(() => _userThumbnail = bytes);
    });
    _portal.portalInfo?.thumbnail?.loadBytes().then((bytes) {
      setState(() => _organizationThumbnail = bytes);
    });
  }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.