Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

OAuth2 client initial contribution #5142

Merged
merged 1 commit into from
Jun 19, 2018
Merged

OAuth2 client initial contribution #5142

merged 1 commit into from
Jun 19, 2018

Conversation

garytse
Copy link
Contributor

@garytse garytse commented Feb 23, 2018

Support getting access token by username password, by authorization code.
Support refresh token
Support caching
No 3rd party library needed
Accounts migration support to be added EDIT: added now

@kaikreuzer
Copy link
Contributor

Thanks for this contribution. Just a first comment: We already have an org.eclipse.smarthome.core.auth package in the core bundle, so I would say that this client does not need to be put into a dedicated bundle, but could rather be placed in a sub-package like org.eclipse.smarthome.core.auth.client (no need for "api" in the package name either).

@kaikreuzer
Copy link
Contributor

but could rather be placed in a sub-package like org.eclipse.smarthome.core.auth.client

Ok, I just noticed that this only works for the api part, but not for the internal implementation as this would introduce a dependency from smarthome.core to Jetty bundles, which we probably do not want.

@kaikreuzer
Copy link
Contributor

FTR: I have moved the implementation to a new bundle org.eclipse.smarthome.auth.oauth2client and the API into the smarthome.core bundle in the package org.eclipse.smarthome.core.auth.client.oauth2.

Copy link
Contributor

@maggu2810 maggu2810 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't found any time to look at the code itself.
Just a short question: Shouldn't new contributions use annotations instead of OSGI-INF/*.xml files?

@garytse
Copy link
Contributor Author

garytse commented Mar 5, 2018

@maggu2810 At code level I am using annotations. Happy to follow if anyone can confirm to remove OSGI-INF/*.xml please?

@kaikreuzer
Copy link
Contributor

@garytse Certainly so, see A.10 of our coding guidelines.

* @author Gary Tse - Initial contribution
*
*/
@Component(name = "org.eclipse.smarthome.auth.oauth2.client.OAuthClientService", servicefactory = true, property = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configurationPid="org.eclipse.smarthome.any.pid", configurationPolicy=REQUIRE would enable the creation of multiple instances of OAuthClientServiceImpl.

If we do this, and if the component has a configuration policy of required as shown above, then we will get multiple instances of the component, with each instance potentially receiving different configuration data. DS will continue to maintain all the service references in our component of course.

*
*/
@Component(name = "org.eclipse.smarthome.auth.oauth2.client.OAuthClientService", servicefactory = true, property = {
"tokenExpiresInBuffer=60" })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also extract this as an externalized configuration through config admin and you can introduce a metatype XML descriptor for that as well.

*
* It is only valid for one-time-only to get the access token.
*
* https://tools.ietf.org/html/rfc6749#section-4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* Redirect URI. This is read by the authorization server. The URI should be
* somewhere in the client application ready to receive the tokens.
*
* {@see https://tools.ietf.org/html/rfc6749#section-3.1.2}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without brackets

*
* If left null, a random state will be generated.
*
* {@see https://tools.ietf.org/html/rfc6749#section-5.2}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without brackets

* {@link https://tools.ietf.org/html/rfc6749#section-1.4}
*
* This token must be confidential in transit and storage.
* https://tools.ietf.org/html/rfc6749#section-10.3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/**
* Token type. e.g. Bearer, MAC
* {@see https://tools.ietf.org/html/rfc6749#section-7.1}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without curly braces


/**
* Number of seconds that this OAuthToken is valid for since the time it was created.
* {@link https://tools.ietf.org/html/rfc6749#section-4.2.2}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@link is for inline methods, constants and so on but @see is for external links

* the client by the resource owner. Unlike access tokens, refresh tokens are
* intended for use only with authorization servers and are never sent
* to resource servers.
* {@link https://tools.ietf.org/html/rfc6749#section-1.5}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@see without braces

* {@link https://tools.ietf.org/html/rfc6749#section-1.5}
*
* This token must be confidential in transit and storage.
* {@link https://tools.ietf.org/html/rfc6749#section-10.4}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@see without braces

* by the authorization server to inform the client of the scope of the access token
* issued.
*
* {@link https://tools.ietf.org/html/rfc6749#section-3.3}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@see without braces

* If the "state" parameter was present in the client authorization request.
* The exact value received from the client.
*
* {@link https://tools.ietf.org/html/rfc6749#section-4.2.2}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@see without braces

* then this call can be used to get a new acess token by using the refresh token.
*
* @param oauthProviderParams
* @param lastOAuthToken refresh token in lastOAuthToken *MUST* be available (not null).
Copy link
Contributor

@amitjoy amitjoy Mar 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can make MUST bold. <b>MUST</b>

* @param lastOAuthToken refresh token in lastOAuthToken *MUST* be available (not null).
* @return new OAuthToken from authorization server. The new token will be saved in store with encryption.
* @throws IOException Web/ network issues etc.
* @throws OAuthError For OAUTH error responses. {@see https://tools.ietf.org/html/rfc6749#section-5.2}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no braces

/**
*
*/
private static final long serialVersionUID = -2548612391437480321L;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty comment blocks can be removed

private static final long serialVersionUID = -2548612391437480321L;

public OAuthException() {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty line

/**
*
*/
private static final long serialVersionUID = -7407238718258981852L;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty javadoc


/**
* Resource Owner Password Credentials (real users' login name)
* {@see https://tools.ietf.org/html/rfc6749#section-1.3.3}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no braces

private String clientId;

/**
* Client secret {@see https://tools.ietf.org/html/rfc6749#section-2.2}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no braces

/**
*
*/
private static final long serialVersionUID = -7394989068336468235L;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty javadoc

* This is for authorization server that uses basic authentication
*
*/
private boolean useBasicAuthentication = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to initialize

* @author Gary Tse - initial contribution
*
*/
public interface TestAgent {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this interface is not part of public API, you can remove it and expose the implementation as a DS Component without any service interface.

Copy link
Contributor Author

@garytse garytse Apr 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used by ConsoleOAuthCommandExtension; refrencing both of the ResourceOwnerTestAgent and AuthorizationCodeTestAgent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can have an interface but it is not necessary. You can expose the implementations as @Component(service = ResourceOwnerTestAgent.class) and @Component(service = AuthorizationCodeTestAgent.class). Since the consumers reside in the same bundle, you don't need a service interface.

Copy link
Contributor Author

@garytse garytse Apr 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for suggestion. If I use (service = ResourceOwnerTestAgent.class)/ (service = AuthorizationCodeTestAgent.class), do I end up only with the public methods from the 2 classes? I mean, the meat is in the abstract super class TestAgent/ AbstractTestAgent

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, only the public methods will be accessible if you are accessing the DS Component from a different package, otherwise you can also access the package private methods if the consumer is in the same package as the DS Components.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, leave it as it is

return secretKey;
}

private static class ConfigurationAdminMock implements ConfigurationAdmin {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of your own custom mock, you can use Mockito which, I believe, already exists in ESH

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched; see next commit.


}

private static class ConfigurationMock implements Configuration {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of your own custom mock, you can use Mockito which, I believe, already exists in ESH

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plan to switch to Mockito?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to Mockito, see next commit.

source.. = src/main/java/
bin.includes = META-INF/,\
.,\
OSGI-INF/org.eclipse.smarthome.auth.oauth2client.internal.OAuthFactoryImpl.xml,\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only OSGI-INF/ will suffice

* @author Gary Tse - Initial Contribution
*
*/
@Component(property = { "CIPHER_TARGET=org.eclipse.smarthome.auth.oauth2client.internal.cipher.SymmetricKeyCipher" })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the curly braces since it can be used for multiple properties.

}
}
} catch (InterruptedException e) {
// if lock is not acquired within the timeout or thread is interruted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thread.currentThread.interrupt()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InterruptedExceptions should never be ignored in the code, and simply logging the exception counts in this case as "ignoring". The throwing of the InterruptedException clears the interrupted state of the Thread, so if the exception is not handled properly the fact that the thread was interrupted will be lost. Instead, InterruptedExceptions should either be rethrown - immediately or after cleaning up the method's state - or the thread should be re-interrupted by calling Thread.interrupt() even if this is supposed to be a single-threaded application. Any other course of action risks delaying thread shutdown and loses the information that the thread was interrupted - probably without finishing its task.

Similarly, the ThreadDeath exception should also be propagated. According to its JavaDoc:

If ThreadDeath is caught by a method, it is important that it be rethrown so that the thread actually dies.

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this contribution, this was quite some work!
Please find some comments below.

org.junit;resolution:=optional,
org.osgi.framework,
org.osgi.service.cm,
org.osgi.service.component.annotations;resolution:=optional,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove, this import is not needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have moved junit tests here, so it should be needed. As for framework/ cm/ annotations, they are used by the test agent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am only talking about "org.osgi.service.component.annotations". This is not needed as the IDE & Tycho provide that already.

org.eclipse.smarthome.io.console,
org.eclipse.smarthome.io.console.extensions,
org.hamcrest;resolution:=optional,
org.json,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not seem to be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used by ConsoleOAuthCommandExtension class. The whole oauth2client.test bundle is not just junit-unit test. It acts like demo + integration + unit tests. The Console part allows the oauth client to be created/ used/ closed/ re-loaded by the console commands. See README.md

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was referring to "org.json".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the comments are put UNDER the commented line by Github, not above it.


public ConsoleOAuthCommandExtension() {
super("oauth", "Test of oauth client with console. Available test agent: {Code, ResourceOwner}.\n"
+ "The commands in oauth requires oauth provider data inputted in configuration admin.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: inputted -> input or put in

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected grammer: "The commands in oauth requires oauth provider data to be inputted in configuration admin."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"inputted" is no English word.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, nevermind then - this surprises me and it looks weird to me (being derived from the verb "put"...)


@Override
public boolean equals(Object thatAuthTokenObj) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

* This is the service factory to produce a OAuth2 service client that authenticates using OAUTH2.
* As this is a service factory pattern, thus the OAuthe2 service client is not shared between bundles.
*
* The basic uses of this OAuthClient is as follows:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: are as follows

PersistedParams params = gson.fromJson(value, PersistedParams.class);
return params;
} catch (Exception e) {
logger.error("Unable to deserialize json {}, discarding PersistedParams", value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

LocalDateTime lastUsedDate = gson.fromJson(value, LocalDateTime.class);
return lastUsedDate;
} catch (Exception e) {
logger.info("Unable to deserialize json {}, reset LocalDateTime to now", value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider json format in statement

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wish to avoid complications if the json itself cannot even be parsed for whatever reason.

storageLock.lock();
try {
if (_storage == null) {
throw new RuntimeException(EXCEPTION_STORAGE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not throw RuntimeException

storageLock.lock();
try {
if (_storage == null) {
throw new RuntimeException(EXCEPTION_STORAGE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not throw RuntimeException

if (_storage == null) {
throw new RuntimeException(EXCEPTION_STORAGE);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

* @param oAuthStoreHandler
*/
@Reference
protected void setoAuthStoreHandler(OAuthStoreHandler oAuthStoreHandler) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to setOAuthStoreHandler

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch; this was generated by eclipse !

this.oAuthStoreHandler = oAuthStoreHandler;
}

protected void unsetoAuthStoreHandler(OAuthStoreHandler oAuthStoreHandler) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to unsetOAuthStoreHandler

@kaikreuzer
Copy link
Contributor

Hey @garytse, are you aware that Travis failed with test compilation errors and that the IP validation failed due to merge commits in the branch? Please fix those two issues and I'll do a final review - thanks!

@kaikreuzer
Copy link
Contributor

@garytse As mentioned in #5142 (comment), please never do merge commits! Instead, rebase your branch on the latest master in order to have a clean PR.

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @garytse, I have done a final review and left some comments - please let me know, if anything is not clear or does not make sense to you.

</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not have m2e nature on any project.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, sorry about that

@@ -0,0 +1,106 @@
eclipse.preferences.version=1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no need for project specific settings, so I'd hope you can remove this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file removed.

@@ -0,0 +1,28 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.smarthome.auth.oauth2client.test
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be something like "Eclipse SmartHome OAuth2Client Tests"

Bundle-Version: 0.10.0.qualifier
Bundle-Vendor: Eclipse.org/SmartHome
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.eclipse.smarthome.auth.oauth2client.test;x-internal:=true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are those packages exported?

Copy link
Contributor Author

@garytse garytse Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see; I have misunderstood the meaning of x-internal.

## Try these on the OSGI console:


smarthome.oauth Code cleanupEverything
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the (ESH default) console, the commands are smarthome oauth..., so the doc should use that format.

protected static final int ACCESS_TOKEN_CACHE_SIZE = 50;

private static final String STORE_NAME = "StorageHandler.For.OAuthClientService";

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the empty lines between the message constants

private class StorageFacade implements AutoCloseable {

// Unusual variable name starting with underscore, _storage.
// This way, it cannot be confused with other storage variables locally in the enclosing class.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And obviously, you should also remove the comment.

}

public void removeByHandle(String handle) {
logger.info("Removing handle {} from storage", handle);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reduce to DEBUG

@Override
public void remove(@NonNull String handle) {
storageFacade.removeByHandle(handle);
// allHandles.remove(handle); // done by storage facade
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line should be removed

if (allHandles.remove(handle)) { // entry exists and successfully removed
if (storage == null) {
// just log the error and let it be, do not throw exception
logger.warn(EXCEPTION_STORAGE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is called for every handle - you wouldn't want to have so many similar WARN messages in the log file; the are not helpful. You hence should decide whether you consider this situation an illegal state (then better throw an exception to the caller) or a valid situation (then there is no need for any log message).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted. throwing IllegalStateException is consistent with the logic.

@garytse
Copy link
Contributor Author

garytse commented Jun 11, 2018

Since the change is quite a lot, I will retest the whole thing again. Will update here once completed.


/**
* Use case 7 - get access token response. The tokens may have been retrieved previously through Use cases: 1d, 2,
* 3,
* 4, 6.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the superfluous line break.

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few small typos and Javadoc issues that I found when looking on your latest commit.

Besides this, all looks good to me. So please let me know once your testing was successful and you have updated the remaining things - we should be good to merge then!

*
* @param handle the handle to the oauth service
* @return the oauth service, or null of the handle does not exist
* @throws OAuthException if the handles does not exist
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "handles" -> "handle"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually contradicts the null return value which states "null of the handle does not exist"

* Gets the oauth service for a given handle
*
* @param handle the handle to the oauth service
* @return the oauth service, or null of the handle does not exist
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: of -> if

* @return An authorization URL during the Authorization Code Grant with http request parameters filled in.
* e.g Produces an URL string like this:
* https://oauth.provider?response_type=code&client_id=myClientId&redirect_uri=redirectURI&scope=myScope&state=mySecureRandomState
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"throws" documentation is missing

@Override
public List<String> getUsages() {
return Arrays.asList(
buildCommandUsage("<agent> create","create an oauth client. Agent:={Code | ResourceOwner}"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I only saw now the Agent:={Code | ResourceOwner}. Not too readable, but ok...

private final Set<String> allHandles = new HashSet<>(); // must be initialized

// gets replaced if Store becomes available. storageFacade handles all the times when
// the actual storage becomes unavilable and locking issues.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: unavilable

@garytse
Copy link
Contributor Author

garytse commented Jun 18, 2018

Testing completed. Many thanks for the comprehensive review and recommendations! I have learnt a lot.

@kaikreuzer
Copy link
Contributor

Perfect, thanks!
Could you then now please squash your commits and add the other author(s) as an Also-By line to the resulting commit message?

Also-by: Kai Kreuzer <kai@openhab.org>
Also-by: Michael Bock <bockm@telekom.de>
Signed-off-by: Gary Tse <gary.tse@telekom.de>
@kaikreuzer kaikreuzer merged commit 032c751 into eclipse-archived:master Jun 19, 2018
@garytse garytse deleted the feature/oauth2 branch June 19, 2018 12:22
@maggu2810
Copy link
Contributor

I have realized that the class OAuthStoreHandlerImpl uses our storage service to get a storage but does not set a classloader the storage should use.
Is this done by intention?

@openhab-bot
Copy link
Contributor

This pull request has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/setup-your-own-openhab-cloud-myopenhab-server-instance/24716/111

@maggu2810
Copy link
Contributor

@garytse Have you seen my comment?

@htreu htreu added this to the 0.10.0 milestone Oct 30, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants