Skip to content

Commit 61b1c36

Browse files
authored
Merge pull request #96 from Esri/vj/oauth
OAuth sample.
2 parents e360058 + 24a8ce2 commit 61b1c36

File tree

8 files changed

+467
-0
lines changed

8 files changed

+467
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2016 Esri.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
17+
package com.esri.samples.portal.oauth;
18+
19+
import javafx.fxml.FXML;
20+
import javafx.fxml.FXMLLoader;
21+
import javafx.scene.control.Alert;
22+
import javafx.scene.control.ButtonType;
23+
import javafx.scene.control.Dialog;
24+
import javafx.scene.control.TextField;
25+
26+
import com.esri.arcgisruntime.security.OAuthConfiguration;
27+
28+
/**
29+
* Custom dialog for getting an OAuthConfiguration.
30+
*/
31+
class AuthenticationDialog extends Dialog<OAuthConfiguration> {
32+
33+
@FXML
34+
private TextField portalURL;
35+
@FXML
36+
private TextField clientID;
37+
@FXML
38+
private TextField redirectURI;
39+
@FXML
40+
private ButtonType cancelButton;
41+
@FXML
42+
private ButtonType continueButton;
43+
44+
AuthenticationDialog() {
45+
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/oauth_auth_dialog.fxml"));
46+
loader.setRoot(this);
47+
loader.setController(this);
48+
49+
setTitle("Authenticate");
50+
51+
try {
52+
loader.load();
53+
} catch (Exception e) {
54+
e.printStackTrace();
55+
}
56+
57+
setResultConverter(dialogButton -> {
58+
if (dialogButton == continueButton) {
59+
if (!portalURL.getText().equals("") && !clientID.getText().equals("") && !redirectURI.getText().equals("")) {
60+
try {
61+
return new OAuthConfiguration(portalURL.getText(), clientID.getText(), redirectURI.getText());
62+
} catch (Exception e) {
63+
Alert alert = new Alert(Alert.AlertType.ERROR);
64+
alert.setContentText(e.getMessage());
65+
alert.show();
66+
}
67+
} else {
68+
Alert alert = new Alert(Alert.AlertType.ERROR);
69+
alert.setContentText("missing credentials");
70+
alert.show();
71+
}
72+
}
73+
return null;
74+
});
75+
}
76+
77+
}
29.7 KB
Loading
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright 2016 Esri.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.esri.samples.portal.oauth;
17+
18+
import java.util.concurrent.CountDownLatch;
19+
20+
import javafx.application.Platform;
21+
import javafx.scene.Scene;
22+
import javafx.scene.web.WebEngine;
23+
import javafx.scene.web.WebView;
24+
import javafx.stage.Modality;
25+
import javafx.stage.Stage;
26+
27+
import com.esri.arcgisruntime.security.AuthenticationChallenge;
28+
import com.esri.arcgisruntime.security.AuthenticationChallengeHandler;
29+
import com.esri.arcgisruntime.security.AuthenticationChallengeResponse;
30+
import com.esri.arcgisruntime.security.AuthenticationChallengeResponse.Action;
31+
import com.esri.arcgisruntime.security.AuthenticationManager;
32+
import com.esri.arcgisruntime.security.OAuthConfiguration;
33+
import com.esri.arcgisruntime.security.OAuthTokenCredential;
34+
import com.esri.arcgisruntime.security.OAuthTokenCredentialRequest;
35+
36+
/**
37+
* Handler to be used when accessing a secured resource.
38+
*/
39+
final class OAuthChallengeHandler implements AuthenticationChallengeHandler {
40+
41+
/**
42+
* Handles challenge before accessing a secured resource.
43+
*
44+
* @param challenge the authentication challenge to handle
45+
* @return the AuthenticationChallengeResponse indicating which action to take
46+
*/
47+
@Override
48+
public AuthenticationChallengeResponse handleChallenge(AuthenticationChallenge challenge) {
49+
try {
50+
// get config such as clientId from the authentication manager
51+
OAuthConfiguration config = AuthenticationManager.getOAuthConfiguration(challenge.getRemoteResource().getUri());
52+
53+
// get the authorization code by sending user to the authorization screen
54+
String authorizationUrl = OAuthTokenCredentialRequest.getAuthorizationUrl(
55+
config.getPortalUrl(), config.getClientId(), config.getRedirectUri(), 0);
56+
String authorizationCode = OAuthChallenge.getAuthorizationCode(authorizationUrl);
57+
58+
// use the authorization code to get a token
59+
OAuthTokenCredentialRequest request = new OAuthTokenCredentialRequest(
60+
config.getPortalUrl(), null, config.getClientId(),null, authorizationCode);
61+
OAuthTokenCredential credential = request.executeAsync().get();
62+
return new AuthenticationChallengeResponse(Action.CONTINUE_WITH_CREDENTIAL, credential);
63+
} catch (Exception e) {
64+
return new AuthenticationChallengeResponse(Action.CANCEL, null);
65+
}
66+
}
67+
}
68+
69+
/**
70+
* This utility class provides a method to display the Authorization Screen as part of the OAuthSample workflow.
71+
*/
72+
final class OAuthChallenge {
73+
74+
/**
75+
* Displays the Authorization Screen prompt to enter user credentials.
76+
*
77+
* @param authorizationUrl URL of the Authorization Screen
78+
* @return authorization code
79+
* @throws Exception if something goes wrong during authorization
80+
*/
81+
static String getAuthorizationCode(String authorizationUrl) throws Exception {
82+
StringBuilder authorizationCode = new StringBuilder();
83+
CountDownLatch authorizationCodeLatch = new CountDownLatch(1);
84+
85+
Platform.runLater(() -> {
86+
// display the authorization screen as a web view
87+
WebView browser = new WebView();
88+
Stage dialog = new Stage();
89+
dialog.initModality(Modality.APPLICATION_MODAL);
90+
dialog.setScene(new Scene(browser, 450, 450));
91+
dialog.show();
92+
WebEngine webEngine = browser.getEngine();
93+
webEngine.load(authorizationUrl);
94+
95+
// read the HTTP response to user action
96+
webEngine.setOnStatusChanged(event -> {
97+
// extract code or error from the location in HTTP response
98+
if (event.getSource() instanceof WebEngine) {
99+
String location = webEngine.getLocation();
100+
if (location.contains("code=")) {
101+
authorizationCode.append(location.split("code=")[1]);
102+
authorizationCodeLatch.countDown();
103+
dialog.close();
104+
} else if (location.contains("error=")) {
105+
authorizationCodeLatch.countDown();
106+
dialog.close();
107+
}
108+
}
109+
});
110+
});
111+
112+
// wait for authorization response
113+
authorizationCodeLatch.await();
114+
115+
return authorizationCode.toString();
116+
}
117+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2016 Esri.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
17+
package com.esri.samples.portal.oauth;
18+
19+
import java.text.SimpleDateFormat;
20+
21+
import com.esri.arcgisruntime.loadable.LoadStatus;
22+
import com.esri.arcgisruntime.portal.Portal;
23+
import com.esri.arcgisruntime.security.AuthenticationManager;
24+
import com.esri.arcgisruntime.security.OAuthConfiguration;
25+
26+
import javafx.fxml.FXML;
27+
import javafx.scene.control.Alert;
28+
import javafx.scene.control.Dialog;
29+
import javafx.scene.control.Label;
30+
import javafx.scene.control.TextField;
31+
32+
public class OAuthController {
33+
34+
@FXML private TextField portalURL;
35+
@FXML private TextField clientId;
36+
@FXML private TextField redirectUri;
37+
@FXML private Label fullName;
38+
@FXML private Label username;
39+
@FXML private Label email;
40+
@FXML private Label memberSince;
41+
@FXML private Label role;
42+
43+
private SimpleDateFormat formatter;
44+
45+
@FXML
46+
private void initialize() {
47+
formatter = new SimpleDateFormat("MMM dd, yyyy");
48+
}
49+
50+
void authenticate() throws Exception {
51+
52+
AuthenticationDialog authenticationDialog = new AuthenticationDialog();
53+
authenticationDialog.show();
54+
authenticationDialog.setOnCloseRequest(r -> {
55+
56+
OAuthConfiguration configuration = authenticationDialog.getResult();
57+
AuthenticationManager.addOAuthConfiguration(configuration);
58+
59+
// setup the handler that will prompt an authentication challenge to the user
60+
AuthenticationManager.setAuthenticationChallengeHandler(new OAuthChallengeHandler());
61+
62+
Portal portal = new Portal("http://" + configuration.getPortalUrl(), true);
63+
portal.addDoneLoadingListener(() -> {
64+
if (portal.getLoadStatus() == LoadStatus.LOADED) {
65+
66+
// display portal user info
67+
fullName.setText(portal.getUser().getFullName());
68+
username.setText(portal.getUser().getUsername());
69+
email.setText(portal.getUser().getEmail());
70+
memberSince.setText(formatter.format(portal.getUser().getCreated().getTime()));
71+
role.setText(portal.getUser().getRole() != null ? portal.getUser().getRole().name() : "");
72+
73+
} else if (portal.getLoadStatus() == LoadStatus.FAILED_TO_LOAD) {
74+
75+
// show alert message on error
76+
showMessage("Authentication failed", portal.getLoadError().getMessage(), Alert.AlertType.ERROR);
77+
}
78+
});
79+
80+
// loading the portal info of a secured resource
81+
// this will invoke the authentication challenge
82+
portal.loadAsync();
83+
});
84+
}
85+
86+
/**
87+
* Display an alert to the user with the specified information.
88+
* @param title alert title
89+
* @param description alert content description
90+
* @param type alert type
91+
*/
92+
private void showMessage(String title, String description, Alert.AlertType type) {
93+
Alert alert = new Alert(type);
94+
alert.setTitle(title);
95+
alert.setContentText(description);
96+
alert.show();
97+
}
98+
99+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2016 Esri.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.esri.samples.portal.oauth;
17+
18+
import javafx.application.Application;
19+
import javafx.fxml.FXMLLoader;
20+
import javafx.scene.Parent;
21+
import javafx.scene.Scene;
22+
import javafx.stage.Stage;
23+
24+
public class OAuthSample extends Application {
25+
26+
@Override
27+
public void start(Stage stage) throws Exception {
28+
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/oauth_controller.fxml"));
29+
Parent root = loader.load();
30+
OAuthController controller = loader.getController();
31+
Scene scene = new Scene(root);
32+
33+
// set title, size, and add scene to stage
34+
stage.setTitle("OAuth Sample");
35+
stage.setWidth(800);
36+
stage.setHeight(700);
37+
stage.setScene(scene);
38+
stage.show();
39+
40+
controller.authenticate();
41+
}
42+
43+
/**
44+
* Opens and runs application.
45+
*
46+
* @param args arguments passed to this application
47+
*/
48+
public static void main(String[] args) {
49+
Application.launch(args);
50+
}
51+
52+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<h1>OAuth</h1>
2+
3+
<p>Demonstrates how to use the OAuth 2.0 protocol for authentication into the ArcGIS platform. Once authenticated, the sample displays the user's profile information.</p>
4+
5+
<p><img src="OAuth.png"/></p>
6+
7+
<h2>How to use the sample</h2>
8+
9+
<p>This sample requires you to setup your own app on arcgis.com. See the <a href="https://github.com/Esri/arcgis-runtime-samples-java/wiki/OAuth">wiki</a> for details.</p>
10+
11+
<p>Enter the details of the application registered on arcgis.com and click sign-in.
12+
This will open a sign-in dialog. After the credentials are entered correctly, the sample
13+
will receive an authorization code from the ArcGIS platform. This authorization code will then be used to obtain an
14+
access token. This access token is used later to access user's profile.</p>
15+
16+
<h2>How it works</h2>
17+
18+
<ol>
19+
<li>Setup an <code>OAuthConfiguration</code> with the settings of an application registered in the ArcGIS platform.</li>
20+
<li>Setup an <code>AuthenticationChallengeHandler</code> that challenges the user for authentication. You could
21+
create a custom handler similar to the one created in this sample: <code>OAuthChallengeHandler</code>.</li>
22+
<li>On trying to access a secured resource, the authentication challenge in invoked.</li>
23+
<li><code>OAuthChallengeHandler</code> directs the user to a sign-in page (using a <code>WebView</code>) from ArcGIS platform.</li>
24+
<li>On successful sign-in, the ArcGIS platform provides an authorization code.</li>
25+
<li>Use the authorization code to create a <code>OAuthTokenCredentialRequest</code>. This will be used by the Runtime
26+
to request an access token. The access token is then used to request a secured resource in the ArcGIS platform.</li>
27+
</ol>
28+
29+
<h2>Features</h2>
30+
31+
<ul>
32+
<li>AuthenticationChallengeHandler</li>
33+
<li>OAuthConfiguration</li>
34+
<li>OAuthTokenCredential</li>
35+
<li>OAuthTokenCredentialRequest</li>
36+
<li>Portal</li>
37+
<li>PortalUser</li>
38+
</ul>

0 commit comments

Comments
 (0)