mirror of
https://github.com/google/nomulus.git
synced 2025-07-24 03:30:46 +02:00
Remove to-be-deprecated OOB OAuth flow in nomulus login (#1625)
This commit is contained in:
parent
bb27feebd6
commit
17d0080742
2 changed files with 93 additions and 10 deletions
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver;
|
||||
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A thin wrapper around {@link LocalServerReceiver} which points the redirect URI to a different
|
||||
* port (the forwarding port) while still listening on the random unused port (the remote port)
|
||||
* nomulus itself picks. This allows us to run the nomulus tool on a remote host (which one can SSH
|
||||
* into) while performing the OAuth 3-legged login flow in a local browser (from the lost host where
|
||||
* the SSH client resides).
|
||||
*
|
||||
* <p>When performing the login flow, an HTTP server will be listening on the remote port and have a
|
||||
* redirect_uri of <code>http://localhost:remote_port</code>, which is only accessible from the
|
||||
* remote host. By changing the redirect_uri to <code>http://localhost:forwarding_port</code>, it
|
||||
* becomes accessible from the local host, if <code>local_host:forwarding_port</code> is forwarded
|
||||
* to <code>remote_host:remote_port</code>.
|
||||
*
|
||||
* <p>Note that port forwarding is <b>required</b>. We cannot use the remote host's IP or reverse
|
||||
* DNS address in the redirect URI, even if they are directly accessible from the local host,
|
||||
* because the only allowed redirect URI scheme for desktops apps when sending a request to the
|
||||
* Google OAuth server is the loopback address with a port.
|
||||
*
|
||||
* @see <href
|
||||
* a=https://developers.google.com/identity/protocols/oauth2/native-app#request-parameter-redirect_uri>
|
||||
* redirect_uri values </href>
|
||||
*/
|
||||
final class ForwardingServerReceiver implements VerificationCodeReceiver {
|
||||
|
||||
private final int forwarding_port;
|
||||
private final LocalServerReceiver localServerReceiver = new LocalServerReceiver();
|
||||
|
||||
ForwardingServerReceiver(int forwarding_port) {
|
||||
this.forwarding_port = forwarding_port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedirectUri() throws IOException {
|
||||
String redirect_uri = localServerReceiver.getRedirectUri();
|
||||
return redirect_uri.replace("localhost:" + getRemotePort(), "localhost:" + forwarding_port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waitForCode() throws IOException {
|
||||
return localServerReceiver.waitForCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws IOException {
|
||||
localServerReceiver.stop();
|
||||
System.out.println("You can now exit from the SSH session created for port forwarding.");
|
||||
}
|
||||
|
||||
int getRemotePort() {
|
||||
return localServerReceiver.getPort();
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ import com.beust.jcommander.Parameters;
|
|||
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
|
||||
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
|
||||
import com.google.api.client.googleapis.extensions.java6.auth.oauth2.GooglePromptReceiver;
|
||||
import java.net.InetAddress;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Authorizes the nomulus tool for OAuth 2.0 access to remote resources. */
|
||||
|
@ -30,24 +30,35 @@ final class LoginCommand implements Command {
|
|||
@Inject @AuthModule.ClientScopeQualifier String clientScopeQualifier;
|
||||
|
||||
@Parameter(
|
||||
names = "--remote",
|
||||
names = "--port",
|
||||
description =
|
||||
"Whether the command is run on a remote host where access to a browser is not available. "
|
||||
+ "If set to true, a URL will be given and a code is expected to be entered after "
|
||||
+ "the user completes authorization by visiting that URL.")
|
||||
private boolean remote = false;
|
||||
"A free port on the local host. When set, it is assumed that the nomulus tool runs on a"
|
||||
+ " remote host whose browser is not accessible locally. i. e. if you SSH to a"
|
||||
+ " machine and run `nomulus` there, the ssh client is on the local host and nomulus"
|
||||
+ " runs on a remote host. You will need to forward the local port specified here to"
|
||||
+ " a remote port that nomulus randomly picks. Follow the instruction when prompted.")
|
||||
private int port = 0;
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
AuthorizationCodeInstalledApp app;
|
||||
if (remote) {
|
||||
if (port != 0) {
|
||||
String remote_host = InetAddress.getLocalHost().getHostName();
|
||||
ForwardingServerReceiver forwardingServerReceiver = new ForwardingServerReceiver(port);
|
||||
app =
|
||||
new AuthorizationCodeInstalledApp(
|
||||
flow,
|
||||
new GooglePromptReceiver(),
|
||||
forwardingServerReceiver,
|
||||
url -> {
|
||||
System.out.println("Please open the following address in your browser:");
|
||||
System.out.println(" " + url);
|
||||
int remote_port = forwardingServerReceiver.getRemotePort();
|
||||
System.out.printf(
|
||||
"Please first run the following command in a separate terminal on your local "
|
||||
+ "host:\n\n ssh -L %s:localhost:%s %s\n\n",
|
||||
port, remote_port, remote_host);
|
||||
System.out.printf(
|
||||
"Please then open the following URL in your local browser and follow the"
|
||||
+ " instructions:\n\n %s\n\n",
|
||||
url);
|
||||
});
|
||||
} else {
|
||||
app = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue