Coder Social home page Coder Social logo

microsoft / oauth2-useragent Goto Github PK

View Code? Open in Web Editor NEW
35.0 55.0 29.0 364 KB

Microsoft OAuth 2.0 User Agent library for Java. Provides classes to facilitate the implementation of "4.1. Authorization Code Grant" from RFC 6749.

License: Other

HTML 0.05% Java 99.95%

oauth2-useragent's Introduction

Microsoft OAuth 2.0 User Agent library for Java 0.11.3

Provides classes to facilitate the implementation of "4.1. Authorization Code Grant" from RFC 6749, specifically by auto-detecting a suitable user-agent (and informing the user if any system requirements are unmet and preventing the use of a user-agent), launching the user-agent and directing it to the authorization endpoint, waiting for the results and returning either the authorization code or the reason for failure.

License

The MIT license can be found in License.txt

Build status

This project has continuous integration hosted by Travis CI: Build Status

What this library provides

There is a UserAgentImpl class (which is mockable via the UserAgent interface it implements).

The requestAuthorizationCode method will perform steps (A)-(C) of the "Authorization Code Flow" (see Figure 3 in section 4.1 of RFC 6749), which is to say:

  1. a browser window (also known as "user-agent") will be opened and directed to the authorization endpoint URI
  2. the user (also known as "resource owner") can then authenticate and decide whether to authorize the client's request
  3. the authorization server will send the browser to the redirect URI with either an authorization code or an error code, which will manifest itself as returning an instance of AuthorizationResponse or throwing an AuthorizationException, respectively

Available user agents and their requirements

The following table summarizes the current support for user agents.

Provider Minimum Java Version Requires desktop? Requires 3rd-party dependency Notes
JavaFX Oracle Java 7 Update 6 (:warning:) Yes No Uses WebView and WebEngine. JavaFx ships with Oracle's Java since version 7 Update 6. OpenJDK 8 users can build & install OpenJFX.
⚠️ Mac OS X 10.11 (El Capitan) and greater only work with Oracle Java 8, because it looks like Java FX is broken on Mac OS X 10.11.
StandardWidgetToolkit (Preview) 1.6 Yes Yes Uses the Standard Widget Toolkit (SWT) from the Eclipse project, which requires the client either ship with the SWT JAR(s) or download them on-demand. This provider will first look in the CLASSPATH for SWT, then look for $HOME/.swt/swt-${arch}.jar, where $HOME represents the user's home directory and ${arch} is either x86 or x86_64, depending on the JVM. The path to the JAR can also be overridden with the SWT_RUNTIME_JAR_PATH property. Please refer to The SWT FAQ for additional information on compatibility and options related to the SWT browser.

Why would I want to use this library?

If you are writing an interactive desktop Java application (also known as "client") that needs to connect to a remote resource protected with OAuth 2.0, then this library is for you. A pop-up window hosting a user agent (web browser) will be presented to the resource owner (user) when they need to authenticate to the remote resource and authorize access to the client. The library monitors the web browser to detect when it tries to visit the redirect URL and intercepts the request to complete the process and close the window.

The web browser monitoring feature avoids

  1. having to register a redirect URI that points to the local machine (which is sometimes impossible) and
  2. hosting a web server on the local machine that would listen for a connection from the web browser.

If you are writing a web-based Java application or an Android app that needs to connect to a remote resource protected with OAuth 2.0, this library won't help you. Consider using something like the Google OAuth Client Library for Java.

Why not use java.awt.Desktop.browse(URI)?

The tradeoffs associated with launching the default [external] browser with a URI entail not having to worry about detecting, shipping and/or hosting a web browser but with the difficulty that external browsers have no built-in, direct way to communicate with other processes. The trick that is often used in OAuth 2.0 scenarios is to get the authorization server to redirect to an address that points to the local computer, which brings about its own set of challenges.

How to use

Maven is the preferred way of referencing this library. Add the following to your POM:

  <dependency>
    <groupId>com.microsoft.alm</groupId>
    <artifactId>oauth2-useragent</artifactId>
    <version>0.11.3</version>
  </dependency>

...and then you can write code like:

public class App {
  public static void main(final String[] args) throws AuthorizationException, URISyntaxException {

    final URI authorizationEndpoint = new URI(args[0]);
    final URI redirectUri = new URI(args[1]);

    final UserAgent userAgent = new UserAgentImpl();

    final AuthorizationResponse authorizationResponse = userAgent.requestAuthorizationCode(authorizationEndpoint, redirectUri);
    final String code = authorizationResponse.getCode();

    System.out.print("Authorization Code: ");
    System.out.println(code);
  }
}

...the resulting program accepts an OAuth 2.0 authorization endpoint URI and a redirect URI to watch for as command-line arguments, then launches a web browser to perform the "Authorization Code Flow" described above.

How to build

If you would like to recompile this library, it's relatively easy.

System requirements

You will need the following software in your PATH:

  1. Oracle JDK 8.
    • Version 8 of the Oracle Java Development Kit is required because of the dependency on JavaFX. You might be able to build using OpenJDK with OpenJFX.
  2. Maven 3.2+

Run a quick build with Maven

  1. Open a command prompt or terminal window.
  2. Run mvn clean verify
    • This will download any Maven plugins you might be missing, compile the code, run some unit tests, and package up the JARs.

Run a more comprehensive build with Maven

Like the "quick build", plus some integration tests will be run, whereby a browser will pop up momentarily a few times.

  1. Open a command prompt or terminal window.
  2. Run mvn clean verify -Dintegration_tests=true

How can I contribute?

Please refer to Contributing.md.

Code of Conduct

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

oauth2-useragent's People

Contributors

alexrukhlin avatar davidstaheli avatar leantk avatar novak avatar olivierdagenais avatar thatsich avatar yacaovsnc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oauth2-useragent's Issues

JavaFX WebView does not load login page

Using the JavaFX provider, the webpage of the login page with the corresponding client_id for authentication is not shown/loaded to display.
The WebView in JavaFX works in principle (tests with other URLs like https://login.microsoftonline.com), but gives a white web page for the page where the actual login prompt is expected.

Does someone know a workaround?

useragent crashes on Mac OSX 10.11

Crashed on my Mac OSX 10.11:

[15:35][yacao@yacao-mac:~/Repos/]$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
[15:35][yacao@yacao-mac:~/Repos/]$ java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x000000011b2fa0a4, pid=81081, tid=2571
#
# JRE version: Java(TM) SE Runtime Environment (7.0_80-b15) (build 1.7.0_80-b15)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.80-b11 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C  [libjfxwebkit.dylib+0x74f0a4]  Java_com_sun_webpane_webkit_network_URLLoader_twkWillSendRequest+0xc1684
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java a>
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

[Windows] HiDPI support on JVM 9+

Currently, StandardWidgetToolkit autnehtication provider gets automatically selected on JVM 9+ (because JavaFX is not usually available on these versions of Java). But it has some DPI problems on Windows. The authentication window looks like that:

image

(note the misplaced elements and unreadable font size in the footer)

It is a known problem of older SWT builds, e.g. see SWT bug 493666.

What's interesting here is that the issue seems to be fixed in newer SWT versions. Updating SWT to <swt.version>4.6.1</swt.version> in the parent pom.xml fixed the issue for me completely.

The way JavaFX provider sets up classpath is problematic

Currently, this is the piece of code we use to locate our own jar and add it to the classpath: (UserAgentImpl.java class)

// TODO: is this the best way to add our JAR?
classPath.add(System.getProperty("java.class.path"));

It turns out this isn't the best way. 😄 In a plugin setting (IntelliJ plugin in this case), our jar is loaded by a plugin classloader and it doesn't appear on the "java.class.path".

Then we got a silent error, tracing the call stack and we see:

Error: Could not find or load main class com.microsoft.alm.oauth2.useragent.JavaFx

Need either a better way to locate our jar, or expose a method to augment the process with correct classpath -- I personally prefer method to augment the classpath so the consumer of this library will be responsible for detecting the correct path. This way consumer has more flexibilities.

JavaFX on Linux needs libxslt.so.1

A user encountered the following error:

java.lang.UnsatisfiedLinkError:
  /path/to/jre1.8.0_60/lib/i386/libjfxwebkit.so: libxslt.so.1: cannot open shared object file: No such file or directory

...it would be nice if the JavaFX provider was able to detect this as part of its compatibility check, possibly by attempting to launch a WebView, to be sure it works.

UserAgent fails to get a code on Ubuntu 15.10

When I ran on Ubuntu 15.10, the subprocess that starts JavaFx has some content in stderr stream:

pci id for fd 21: 80ee:beef, driver (null)
libGL error: core dri or dri2 extension not found
libGL error: failed to load driver: vboxvideo

The process still loads up the JavaFx provider and retrieves a code successfully. I can see the code from stdout. However since we have this check:

  if (errorContents.length() > 0)

we just throw and quit.

We probably should verify the stdout and ignore stderr stream if the code is returned proper.

A fatal error in a subprocess is relayed as a very long, URL-encoded exception message

A fatal error (like the one caused by issue #22) currently causes the stack trace to contain something that looks like:

Caused by: error=unknown_error&error_description=Exception+in+Application+start+method%0AException+in+Application+stop+method%0Ajava.lang.reflect.InvocationTargetException%0A%09at+sun.reflect.NativeMethodAccessorImpl.invoke0%28Native+Method%29%0A%09at
(...goes on for several "lines"...)
%09...+1+more%0AException+running+application+com.microsoft.alm.oauth2.useragent.JavaFx%0A

At the very least, we should URL-decode the output so it can be formatted nicely.

File Separator

Hi :
We found a problem about File Separator in oauth2-useragent.Different operating systems use different characters as file separators. For example, Microsoft Windows systems use "", while UNIX systems use "/". When applications have to run on different platforms, the use of hardcoded file separators can lead to incorrect execution of application logic and potentially a denial of service.
com.microsoft.alm.oauth2.useragent.JavaFxProvider
image
advice: use ”File.separator“ replace “/”

Seamless authentication is not happening

While performing OIDC authentication, browser window opens and in that it asks for user credentials and then pass the code. Ideally when i am on the network, seamless authentication should have been done. Does it supports that or not?

UserAgent should expose a function to check for requirements

As of now, the only way to know UserAgent won't work is to call it, then expect an IllegalStateException.

It would be good to expose the requirement checking function publicly, so we can determine if UserAgent is suitable or not, and then decide if we should go ahead to make the call, or fall back to other mechanism.

As of now I am controlling code flow by exception, and I don't think that's a good pattern.

User Agent Provider not properly recognized

I haven't gone into it in a lot of detail so there isn't much I can tell, but an external executable .jar was not able to find the proper UserAgentProvider, thus resulting in the authorization window never popping up.

A quick and easy hack is to explicitly set the UserAgentProvider with

System.getProperties().setProperty("userAgentProvider", "JavaFx");

I'm merely posting the issue here with the hope of saving someone else several hours of debugging. This issue occurred in a .jar artifact, but not in the IntelliJ IDE.

Browser window is inactive - Can't retrieve an authorization code

Hello,
I have just discovered this library and was hoping to be able to use it.

The issue that I am encountering is the following :
I have created a sample code to retrieve an authorization code from the Dropox API (see code below).

 final UserAgent userAgent = new UserAgentImpl();
      AuthorizationResponse authorizationResponse;
      try {
         final URI authorizationEndpoint = new URI("https://www.dropbox.com/oauth2/authorize?" +
               "client_id=MYCLIENTID" +
               "&response_type=code" +
               "&force_reapprove=true");
         final URI redirectUri = new URI("");
         authorizationResponse = userAgent.requestAuthorizationCode(authorizationEndpoint,
               redirectUri);
         final String code = authorizationResponse.getCode();
         System.out.print("Authorization Code: ");
         System.out.println(code);
      } catch (final AuthorizationException | URISyntaxException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

Once the browser window is loaded, if I enter my Dropbox credentials or if I use Google to authenticate myself, clicking on the Login button or Next doesn't trigger anything.

image

I don't see any exceptions being raised.

Thanks

StandardWidgetTool failed to get Authorization Code on RHEL 7.2 with OpenJDK

@leantk ran into this problem today on her RHEL 7.2 box. The SWT browser came up fine and works against MSA backed account. However when she tries to login with her work email address, SWT throws this stack trace when it should prompt for 2FA:

com.microsoft.alm.oauth2.useragent.AuthorizationException: Code: unknown_error Description: openjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-b14)
OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)

                at com.microsoft.alm.oauth2.useragent.AuthorizationResponse.fromString(AuthorizationResponse.java:109)
                at com.microsoft.alm.oauth2.useragent.UserAgentImpl.encode(UserAgentImpl.java:190)
                at com.microsoft.alm.oauth2.useragent.UserAgentImpl.requestAuthorizationCode(UserAgentImpl.java:150)
                at com.microsoft.alm.auth.oauth.AzureAuthority.acquireAuthorizationCode(AzureAuthority.java:282)
                at com.microsoft.alm.auth.oauth.AzureAuthority.acquireToken(AzureAuthority.java:223)
                at com.microsoft.alm.auth.oauth.OAuth2Authenticator$1.doRetrieve(OAuth2Authenticator.java:181)
                at com.microsoft.alm.auth.oauth.OAuth2Authenticator$1.doRetrieve(OAuth2Authenticator.java:157)
                at com.microsoft.alm.auth.BaseAuthenticator$SecretRetriever.retrieve(BaseAuthenticator.java:217)
                at com.microsoft.alm.auth.oauth.OAuth2Authenticator.getOAuth2TokenPair(OAuth2Authenticator.java:208)
                at com.microsoft.alm.auth.pat.VstsPatAuthenticator$1.doRetrieve(VstsPatAuthenticator.java:141)
                at com.microsoft.alm.auth.pat.VstsPatAuthenticator$1.doRetrieve(VstsPatAuthenticator.java:138)
                at com.microsoft.alm.auth.BaseAuthenticator$SecretRetriever.retrieve(BaseAuthenticator.java:217)
                at com.microsoft.alm.auth.pat.VstsPatAuthenticator.getToken(VstsPatAuthenticator.java:157)
                at com.microsoft.alm.auth.pat.VstsPatAuthenticator.getPersonalAccessToken(VstsPatAuthenticator.java:112)
                at com.microsoft.alm.provider.JaxrsClientProvider.getClient(JaxrsClientProvider.java:109)
                at com.microsoft.alm.auth.sample.App.main(App.java:72)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

She tries the same work email login on my RHEL 6.7 VM with the same OpenJDK 8 (1.8.0_91) version, and SWT works fine, she sees the 2FA.

Looks like this is a problem on RHEL 7.2.

useragent crashes on Mac OSX 10.12.6 with JDK 1.8.0_131

Similar to #8
The version of java though is 1.8.0_131-b11
After updating to this version - the useragent crashes.

The behavior is that the login "browser" window appears, loads and when hovered with a mouse or after some time it vanishes leaving the crash report.

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fffc27fcfcc, pid=33916, tid=0x0000000000000307
#
# JRE version: Java(TM) SE Runtime Environment (8.0_131-b11) (build 1.8.0_131-b11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C  [libsystem_platform.dylib+0x5fcc]  _platform_memmove$VARIANT$Haswell+0x12c

VM env:

VM Arguments:
jvm_args: -Djava.protocol.handler.pkgs=com.microsoft.alm.oauth2.useragent -Dhttp.nonProxyHosts=local|*.local|169.254/16|*.169.254/16 -Djava.net.useSystemProxies=true 
java_command: com.microsoft.alm.oauth2.useragent.JavaFx requestAuthorizationCode
java_class_path (initial): /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/usr/local/Cellar/git-credential-manager/2.0.3/libexec/git-credential-manager-2.0.3.jar
Launcher Type: SUN_STANDARD

System info:

OS:Bsduname:Darwin 16.7.0 Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64 x86_64
rlimit: STACK 8192k, CORE 0k, NPROC 709, NOFILE 10240, AS infinity
load average:3.18 3.07 2.75

CPU:total 8 (initial active 8) (4 cores per cpu, 2 threads per core) family 6 model 70 stepping 1, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, avx, avx2, aes, clmul, erms, lzcnt, ht, tsc, tscinvbit, bmi1, bmi2

Memory: 4k page, physical 16777216k(215136k free)

/proc/meminfo:


vm_info: Java HotSpot(TM) 64-Bit Server VM (25.131-b11) for bsd-amd64 JRE (1.8.0_131-b11), built on Mar 15 2017 01:32:22 by "java_re" with gcc 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)

time: Tue Aug  8 06:37:33 2017
elapsed time: 14 seconds (0d 0h 0m 14s)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.