All Projects → nextcloud → Android-SingleSignOn

nextcloud / Android-SingleSignOn

Licence: GPL-3.0 license
Single sign-on for Nextcloud (Android Library Project)

Programming Languages

java
68154 projects - #9 most used programming language
ruby
36898 projects - #4 most used programming language
shell
77523 projects
AIDL
53 projects

Projects that are alternatives of or similar to Android-SingleSignOn

Qownnotes
QOwnNotes is a plain-text file notepad and todo-list manager with markdown support and Nextcloud / ownCloud integration.
Stars: ✭ 2,357 (+3701.61%)
Mutual labels:  nextcloud
Nextcloud Spreed Signaling
Standalone signaling server for Nextcloud Talk.
Stars: ✭ 201 (+224.19%)
Mutual labels:  nextcloud
firstrunwizard
🔮 The first impression matters. The firstrunwizard is the first Nextcloud impression.
Stars: ✭ 34 (-45.16%)
Mutual labels:  nextcloud
Floccus
☁️ Sync your bookmarks privately across browsers
Stars: ✭ 2,630 (+4141.94%)
Mutual labels:  nextcloud
Cookbook
🍲 A library for all your recipes
Stars: ✭ 195 (+214.52%)
Mutual labels:  nextcloud
Server
☁️ Nextcloud server, a safe home for all your data
Stars: ✭ 17,723 (+28485.48%)
Mutual labels:  nextcloud
Ocsms
📱 Nextcloud/ownCloud PhoneSync server application
Stars: ✭ 163 (+162.9%)
Mutual labels:  nextcloud
viewer
🖼 Simple file viewer with slideshow for media
Stars: ✭ 68 (+9.68%)
Mutual labels:  nextcloud
Client theming
💻 Nextcloud themed desktop client - Moved over to https://github.com/nextcloud/desktop
Stars: ✭ 201 (+224.19%)
Mutual labels:  nextcloud
Maps
🌍🌏🌎 The whole world fits inside your cloud!
Stars: ✭ 253 (+308.06%)
Mutual labels:  nextcloud
Audioplayer
Audio Player for Nextcloud and ownCloud
Stars: ✭ 179 (+188.71%)
Mutual labels:  nextcloud
Richdocuments
📔 Collabora Online for Nextcloud
Stars: ✭ 193 (+211.29%)
Mutual labels:  nextcloud
Facerecognition
Nextcloud app that implement a basic facial recognition system.
Stars: ✭ 226 (+264.52%)
Mutual labels:  nextcloud
Nextcloud Drawio
Draw.io intergration app
Stars: ✭ 177 (+185.48%)
Mutual labels:  nextcloud
docker-nextcloud
Nextcloud Docker image
Stars: ✭ 209 (+237.1%)
Mutual labels:  nextcloud
Nextcloud.com
🌏 Our website
Stars: ✭ 164 (+164.52%)
Mutual labels:  nextcloud
Android
📱 Nextcloud Android app
Stars: ✭ 2,669 (+4204.84%)
Mutual labels:  nextcloud
aws-serverless-nextcloud
moved - https://github.com/f7o/aws-serverless-nextcloud
Stars: ✭ 78 (+25.81%)
Mutual labels:  nextcloud
nextcloud announcements
ℹ️ The latest Nextcloud news directly in your notifications
Stars: ✭ 16 (-74.19%)
Mutual labels:  nextcloud
Baiyue onekey
佰阅部落一键脚本合集工具箱,集合25+优质开源项目,一步到位,全程中文交互提示,不懂代码也可以轻松搭建很多程序
Stars: ✭ 246 (+296.77%)
Mutual labels:  nextcloud

Nextcloud Single Sign On

Codacy Badge Last release GitHub issues GitHub stars License: GPL v3

This library allows you to use accounts as well as the network stack provided by the nextcloud files app. Therefore you as a developer don't need to worry about asking the user for credentials as well as you don't need to worry about self-signed ssl certificates, two factor authentication, save credential storage etc.

Please note that the user needs to install the nextcloud files app in order to use those features. While this might seem like a "no-go" for some developers, we still think that using this library is worth consideration as it makes the account handling much faster and safer.

How to use this library

You can check out the sample app which uses this library to fetch some information via SSO from a Nextcloud instance. The sample app uses the Retrofit approach. Be aware though, that it is for demonstration purposes only. Exception handling, state management etc. must be implemented depending on your use case.

1) Add this library to your project

repositories {
    //
    maven { url "https://jitpack.io" }
}

dependencies {
    // Note: Android Gradle Plugin (AGP) version ≥ 7.0.0 is required.
    implementation "com.github.nextcloud:Android-SingleSignOn:0.6.0"
}

2) To choose an account, include the following code in your login dialog

private void openAccountChooser() {
    try {
        AccountImporter.pickNewAccount(activityOrFragment);
    } catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
        UiExceptionManager.showDialogForException(this, e);
    }
}

3) To handle the result of the Account Chooser, include the following

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    AccountImporter.onActivityResult(requestCode, resultCode, data, this, new AccountImporter.IAccountAccessGranted() {

        @Override
        public void accountAccessGranted(SingleSignOnAccount account) {
            final var context = getApplicationContext();

            // As this library supports multiple accounts we created some helper methods if you only want to use one.
            // The following line stores the selected account as the "default" account which can be queried by using
            // the SingleAccountHelper.getCurrentSingleSignOnAccount(context) method
            SingleAccountHelper.setCurrentAccount(context, account.name);

            // Get the "default" account
            SingleSignOnAccount ssoAccount = null;
            try {
                ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
            } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
                UiExceptionManager.showDialogForException(context, e);
            }

            final var nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create());

            // TODO … (see code in section 4 and below)
        }
    });
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    AccountImporter.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

// Complete example: https://github.com/nextcloud/news-android/blob/890828441ba0c8a9b90afe56f3e08ed63366ece5/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogActivity.java#L470-L475

4) How to get account information?

// If you stored the "default" account using setCurrentAccount(…) you can get the account by using the following line:
final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);

// Otherwise (for multi-account support you'll have to keep track of the account names yourself. Note: this has to be the name of SingleSignOnAccount.name)
AccountImporter.getSingleSignOnAccount(context, accountName);

ssoAccount.name; // Name of the account used in the android account manager
ssoAccount.username;
ssoAccount.token;
ssoAccount.url;

5) How to make a network request?

public NextcloudAPI(Context context, SingleSignOnAccount account, Gson gson) {

You'll notice that there is an optional ApiConnectedListener callback parameter in the constructor of the NextcloudAPI. You can use this callback to subscribe to errors that might occur during the initialization of the API. You can start making requests to the API as soon as you instantiated the NextcloudAPI object. The callback method onConnected will be called once the connection to the files app is established. You can start making calls to the api before that callback is fired as the library will queue your calls until the connection is established¹.

5.1) Using Retrofit

5.1.1) Before using this single sign on library, your interface for your retrofit API might look like this:
public interface API {

    String mApiEndpoint = "/index.php/apps/news/api/v1-2/";

    @GET("user")
    Observable<UserInfo> user();

    // use ParsedResponse, in case you also need the response headers. Works currently only for Observable calls.
    @GET("user")
    Observable<ParsedResponse<UserInfo>> user();

    @POST("feeds")
    Call<List<Feed>> createFeed(@Body Map<String, Object> feedMap);

    @DELETE("feeds/{feedId}")
    Completable deleteFeed(@Path("feedId") long feedId);

    // …
}

You might instantiate your retrofit API by using something like this:

public class ApiProvider {

    private final API mApi;

    public ApiProvider() {
        mApi = retrofit.create(API.class);
    }
}
5.1.2) Use of new API using the nextcloud app network stack
public class ApiProvider {

    private final API mApi;

    public ApiProvider(@NonNull NextcloudAPI.ApiConnectedListener callback) {
       final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
       final var nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), callback);
       mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
   }
}

Enjoy! If you're already using retrofit, you don't need to modify your application logic. Just exchange the API and you're good to go!

Note: If you need a different mapping between your json-structure and your java-structure you might want to create a custom type adapter using new GsonBuilder().create().registerTypeAdapter(…). Take a look at this example for more information.

5.2) Without Retrofit

NextcloudAPI provides a method called performNetworkRequest(NextcloudRequest request) that allows you to handle the server response yourself.

public class MyActivity extends AppCompatActivity {

    private NextcloudAPI mNextcloudAPI;

    @Override
    protected void onStart() {
        super.onStart();
        try {
            final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(this);
            mNextcloudAPI = new NextcloudAPI(this, ssoAccount, new GsonBuilder().create());

            // Start download of file in background thread (otherwise you'll get a NetworkOnMainThreadException)
            new Thread(this::downloadFile).start();
        } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
            // TODO handle errors
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Close Service Connection to Nextcloud Files App and
        // disconnect API from Context (prevent Memory Leak)
        mNextcloudAPI.stop();
    }

    private void downloadFile() {
        final List<Pair<String, String>> parameters = new ArrayList<>();
        parameters.add(new QueryPair("quality", "1024p"));
        parameters.add(new Pair<>("someOtherParameter", "parameterValue"));
        
        final var nextcloudRequest = new NextcloudRequest.Builder()
                .setMethod("GET")
                .setParameter(parameters)
                .setUrl(Uri.encode("/remote.php/webdav/sample movie.mp4","/"))
                .build();

        try (final var inputStream = mNextcloudAPI.performNetworkRequest(nextcloudRequest)) {
            while(inputStream.available() > 0) {
                inputStream.read();
                // TODO do something useful with the data here..
                // like writing it to a file…?
            }
        } catch (Exception e) {
            // TODO handle errors
        }
    }
}

5.3) WebDAV

The following WebDAV Methods are supported: PROPFIND / MKCOL

The following examples shows how to use the PROPFIND method. With a depth of 0.

final List<String> depth = new ArrayList<>();
depth.add("0");
header.put("Depth", depth);

final var nextcloudRequest = new NextcloudRequest.Builder()
        .setMethod("PROPFIND")
        .setHeader(header)
        .setUrl(Uri.encode("/remote.php/webdav/" + remotePath, "/"))
        .build();

Additional info

In case that you require some sso features that were introduced in a specific nextcloud files app version, you can run a simple version check using the following helper method:

final int MIN_NEXTCLOUD_FILES_APP_VERSION_CODE = 30030052;

if (VersionCheckHelper.verifyMinVersion(context, MIN_NEXTCLOUD_FILES_APP_VERSION_CODE, FilesAppType.PROD)) {
   // Version requirement is satisfied!
}

Security

Once the user clicks on "Allow" in the login dialog, the Nextcloud Files App will generate a token for your app. Only your app is allowed to use that token. Even if another app will get a hold of that token, it won't be able to make any requests to the nextcloud server as the nextcloud files app matches that token against the namespace of your app.

Media

Talks at the Nextcloud Conference

2018 (5min) 2020 (5min)
Nextcloud Single Sign On for Android David Luhmer Nextcloud Single Sign On for Android David Luhmer

Demo video

Demo video

Known apps

Troubleshooting

If you are experiencing any issues, the following tips might workaround:

Flow Diagram

Note that the "Make network request" section in the diagram only shows the workflow if you use the "retrofit" api.

Flow Diagram

Translations

We manage translations via Transifex. So just request joining the translation team for Android on the site and start translating. All translations will then be automatically pushed to this repository, there is no need for any pull request for translations.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].