Skip to content
This repository has been archived by the owner on Jun 19, 2023. It is now read-only.

OAuth2 support #919

Merged
merged 222 commits into from
Nov 8, 2017
Merged

OAuth2 support #919

merged 222 commits into from
Nov 8, 2017

Conversation

nasli
Copy link
Contributor

@nasli nasli commented Jul 11, 2017

Closes #716, closes #877

Description

Login will be done via OAuth2 protocol when server version supports it.

AC:

  • Extend detection of authentication method to consider servers accepting more than one method at the same time (more than one challenge header can be received in responses). (Create new swift class to detect all authentications methods available )

  • Embed oauth log-in process into WebView

    • Create new storyboard to handle new login view flow
    • Create new view controller that manage new view
    • Launch new view after help guide view
    • Refactor check url in new view Connect new class with previous check url method
    • Refactor parse url
    • Detect auth method to login that server and app support
    • connect SAML log in
    • connect old delegates in SAML, close login view and show filelistView
    • if SAML enabled only support SAML as valid auth method
    • oauth in webview
    • oauth webview in full screen for ipad too
    • Basic auth log in
    • refactor load app with properly Login mode (create,update,expire,migrate), remove all references to old edit and add account views
    • logic to different modes in universal login view
      • Add Account
      • Refactor update user with credentials in keychain
      • Edit Account
      • Migrate Account
      • Error Credentials
    • review login view and call show error when needed
    • auto complete user an password fields if exist within the url
    • Add upgrade keychain items with new auth credentials data values
  • UI/UX improvements

    • Handle errors below url
    • Set branded style in view (colors,text status white)
      • Set branded color error labels
    • Show/hide help link in login view
    • show user, password, error labels
    • use and update constraits to url user password changes (stacks views, fixed height) @pablocarmu
    • show/hide eye button to show password without encryption @pablocarmu
    • Text fields
  • Recover / implement authentication workflow via "authorization code grant".

    • brand new options
    • get auth code
    • get token with code
    • update credentials object, update keychain method
    • request with access token, refactor get list of files
    • unwind to main login view
    • refactor store user with credentials in keychain
    • refactor store user account
    • load file list view
  • Redirect to log-in view when access token is not valid and cannot be refreshed, or when SAML session expires , or when password is not valid anymore.

  • Silently use refresh token to get an access token on expiration instead of redirecting to log-in view. MOVED to Silently refresh OAuth2 access token if expired #928

  • NICE2HAVE: Allow user to select authentication method (OAuth2 or Basic Auth) [WON'T FIX]

  • clean logs– MOVED to Silently refresh OAuth2 access token if expired #928

*Note: Tasks are not in priority order

How Has This Been Tested?

@nasli nasli requested a review from davivel July 11, 2017 07:25
@nasli nasli added this to the 3.7.0 milestone Jul 11, 2017
@property (nonatomic, copy) NSString *userName;
@property (nonatomic, copy) NSString *password;
@property (nonatomic, copy) NSString *password; //or accessToken in oauth
Copy link
Contributor

Choose a reason for hiding this comment

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

I would call it accessToken, seems more general; then explain in the comment that password goes there for basic auth.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@@ -33,6 +34,8 @@ typedef enum {
@property (nonatomic, copy) NSString *url;
@property (nonatomic, copy) NSString *username;
@property (nonatomic, copy) NSString *password;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since password will be contained in credDto, password property needs to disappear.

Copy link
Contributor Author

@nasli nasli Jul 11, 2017

Choose a reason for hiding this comment

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

👍 pending, check also remove username

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 Password already removed

@@ -19,6 +19,9 @@
@interface OCKeychain : NSObject

+(BOOL)setCredentialsById:(NSString *)idUser withUsername:(NSString *)userName andPassword:(NSString *)password;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the chance to rename the first parameter in all the other methods to userId instead of idUser.

Copy link
Contributor Author

@nasli nasli Jul 11, 2017

Choose a reason for hiding this comment

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

👍 pending

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 done


BOOL output = NO;

NSMutableDictionary *keychainItem = [NSMutableDictionary dictionary];

[keychainItem setObject:(__bridge id)(kSecClassGenericPassword) forKey:(__bridge id)kSecClass];
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious, why kSecClassInsternetPassword instead of kSecClassGenericPassword ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doesn't matter, just I want to use some key that are by default in the kSecClass kSecClassInsternetPassword as kSecAttrAuthenticationType. This was first approach but after I store all as data. This keychain method maybe not be the final, it is not in use yet. At this moment we can keep using kSecClassGenericPassword because I no longer use the other attributes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What it is recommended is for passcodes inside the app use GenericPassword and for pass used with connections in websites the kSecClassInsternetPassword that has more defaults attributes related connections

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍


// MARK: CheckAccessToServer delegate

func connection(toTheServer isConnection: Bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Definitely, we need a better way to name delegate methods.

For this case, what do you think about something like connectionWasChecked

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 but very careful with the refactor.. it it's used in a lot of places in the app

Copy link
Contributor Author

Choose a reason for hiding this comment

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

pending

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 Already improved


if (data != nil) {
//getfiles, if ok store new account
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We should do something with the else case. At least, write an info log.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍



// MARK: segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the valid form or is the one in commented below?

Copy link
Contributor Author

@nasli nasli Jul 11, 2017

Choose a reason for hiding this comment

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

This one, I will remove the commented one that is for previous swift 2.0 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

#define k_oauth2_redirect_uri @"oc://android.owncloud.com"
#define k_oauth2_client_id @"e4rAsNUSIUs0lF4nbv9FmCeUkTlV9GdgTLDH1b5uie7syb90SzEVrbN7HIpmWJeD"
#define k_oauth2_client_secret @"dInFYGV33xKzhbRmpqQltYNdfLdJIfJ9L5ISoKhNoT9qZftpdWSP71VrpGR9pmoD"
//#define k_oauth2_redirect_uri @"oc://ios.owncloud.com"
Copy link
Member

Choose a reason for hiding this comment

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

@nasli what will be the final values? I will adjust the oauth server app then thx

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can use this ones commented, I got them from core commented code

@jesmrec jesmrec changed the title [WIP] Oauth2 support [WIP] OAuth2 support Jul 18, 2017
@davivel davivel added the login label Aug 17, 2017
@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG [FIXED]

Problems when log-in is confirmed tapping on 'connect' button instead of on 'enter' in keyboard

Steps to reproduce

  1. add account to server with basic auth support only, type URL, user and password
  2. tap connect button to confirm password (do not tap 'enter' in soft keyboard

Expected behaviour

Keyboard is dismissed, account is created

Current behaviour

Keyboard is not dismissed, account is created twice

@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG [FIXED]

Crash on update of OAuth credentials

Steps to reproduce

  1. add an account in a server supporting OAuth 2
  2. tap on settings, then tap on button to edit the account added in 1

Expected behaviour

Log-in view in edit mode is shown

Current behaviour

Crash

@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG (1) [FIXED]

Log-in view for OAuth 2 appears from nowhere

Steps to reproduce

  1. Add an OAuth2 account to the app.
  2. Add a new account with Basic Auth to other server

Expected behaviour

The log-in view disappears and the list of accounts or the list of files is shown

Current behaviour

A new log-in view appears, showing the OAuth account as expired, and a cancel button disabled, blocking the usage of the app, til the point that requires reinstalling it .

@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG (2) [FIXED]

Log-in with HTTP prefix shows wrong error

Steps to reproduce

  1. Add a new account; type an HTTP URL to a valid server that supports OAuth; type enter to check the URL

Expected behaviour:

Check is successful

Current behaviour:

"Redirect to an unsecure route" is shown after the check

@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG (3) [FIXED]

Connect button disabled after parsing URL that includes username and password

Steps to reproduce:

  1. In the log-in view, type a URL including username and password inline, such as https://[user]:[pass]@[rest_of_the_url]
  2. Tap on 'enter' in the keyboard

Expected behaviour:

After the URL is successfully checked, username and password input fields are shown, filled with the user and password from the URL; focus is on the password field; 'connect' button is enabled

Current behaviour:

After the URL is successfully checked, username and password input fields are shown, filled with the user and password from the URL; focus is on the username field; 'connect' button is disabled

@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG (4) [FIXED]

Wrong password not detected in edit mode

Steps to reproduce

  1. Add an OAuth account (1)
  2. Add a Basic Auth account (2)
  3. Edit the account (2), change the password for a wrong one.
  4. Tap on account (2) in list of accounts, wrong password is detected an log-in view shown in expired mode
  5. Enter wrong password again

Expected behaviour

  1. Wrong password is detected and account is not updated; user has to type in the correct password or cancel; the rest of the steps cannot be done

Current behaviour

  1. Wrong password is accepted and stored.
  2. App crashes.

NOTE @jesmrec (01/09/2017): Wrong passwords are detected but the app crashes if the "wrong" tries persists. Twice "Edit credentials" make the app crash

@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG (5) [FIXED]

Wrong padding between top bar and OC icon in log-in view

Steps to reproduce

  1. Install the app
  2. Open the app, log-in view appears

Expected behaviour

Space between top bar and OC icon is the same as in subsequent displays of log-in view

Current behaviour

Space between top bar and OC icon is smaller than in subsequent displays of log-in view

@davivel
Copy link
Contributor

davivel commented Aug 17, 2017

BUG (6) [NOT REPRODUCIBLE]

Disabled cancel button shown in navigation bar unexpectedly.

Steps to reproduce

Not clear.



- (void)showLoginView:(UniversalLoginViewController *)loginView {
//TODO: move to utils login, and window var
Copy link
Contributor

Choose a reason for hiding this comment

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

Here is a TODO pending i think

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 Removed

@@ -2836,17 +2769,87 @@ - (void) showSplashScreenFake {

#pragma mark - CheckAccessToServerDelegate

-(void)connectionToTheServer:(BOOL)isConnection {
-(void)connectionToTheServerWasChecked:(BOOL)isConnected withHttpStatusCode:(NSInteger)statusCode andError:(NSError *)error {
Copy link
Contributor

Choose a reason for hiding this comment

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

same code in 3 different functions(connectionToTheServerWasChecked, repeatTheCheckToTheServer, badCertificateNotAcceptedByUser), maybe we can extract this piece of code into a single one function and then call it inside every one of this functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 CheckAccessToServer still need improvements..


#pragma mark - Active User

- (void) switchActiveUserTo:(UserDto *)user inHardMode:(BOOL)hardMode withCompletionHandler:(void (^)(void)) completionHandler {
Copy link
Contributor

Choose a reason for hiding this comment

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

This function is called only one time and with "inHardMode" set to NO, so why is this parameter useful?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -122,7 +122,7 @@ - (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)
- (void)eraseDataSwitchChanged:(id)sender
{
if (_eraseDataSwitch.on) {
NSString* title = [NSString stringWithFormat:KKPasscodeLockLocalizedString(@"All data in this app will be erased after %d failed passcode attempts.", @""), [[KKPasscodeLock sharedLock] attemptsAllowed]];
// NSString* title = [NSString stringWithFormat:KKPasscodeLockLocalizedString(@"All data in this app will be erased after %d failed passcode attempts.", @""), [[KKPasscodeLock sharedLock] attemptsAllowed]];
Copy link
Contributor

Choose a reason for hiding this comment

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

Commented code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's leave this one, it's a feature in this library not in use right now

import Foundation


//class Log {
Copy link
Contributor

Choose a reason for hiding this comment

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

full commented class

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Intent to log of swift classes, let's review in release state.

self.readFolderOfURL(url, credentials: credentials, success: { (_ listOfFiles: [Any]?) in
var listOfFileDtos: [FileDto]? = nil

if (listOfFiles != nil && !((listOfFiles?.isEmpty)!)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this set of "(" and "!" , ((listOfFiles?.isEmpty)!), could be avoided if previously you ensures that the "listOfFiles" exist and is not nil, maybe with an "if let ..." statement.

Copy link
Contributor Author

@nasli nasli Nov 8, 2017

Choose a reason for hiding this comment

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

👍 Improvement done to check files content

@@ -554,7 +555,7 @@ - (void)showError:(NSString *) message {
[alert addAction:ok];

if ([self.navigationController isViewLoaded] && self.navigationController.view.window && self.resolveCredentialErrorViewController != nil) {
[self.resolveCredentialErrorViewController presentViewController:alert animated:YES completion:nil];
//TODO:check bridging [self.resolveCredentialErrorViewController presentViewController:alert animated:YES completion:nil];
Copy link
Contributor

Choose a reason for hiding this comment

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

Yet Another TODO 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.

👍

@@ -31,7 +31,7 @@
@property(nonatomic, weak) __weak id <AccountCellDelegate> delegate;


- (IBAction)activeAccount:(id)sender;
//- (IBAction)activeAccount:(id)sender;
Copy link
Contributor

Choose a reason for hiding this comment

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

Commented 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.

👍

@@ -24,6 +24,7 @@

@implementation AccountCell

//TODO: use autolayout for cell
Copy link
Contributor

Choose a reason for hiding this comment

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

Another TODO

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@@ -40,16 +41,13 @@ - (void)setSelected:(BOOL)selected animated:(BOOL)animated
// Configure the view for the selected state
}

/*
Copy link
Contributor

Choose a reason for hiding this comment

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

Commented Code

Copy link
Contributor Author

@nasli nasli Nov 7, 2017

Choose a reason for hiding this comment

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

👍 Removed, and also removed remaining references in xib file, account cell classes an setting class

@nasli nasli merged commit fd8e411 into master Nov 8, 2017
@jesmrec jesmrec mentioned this pull request Nov 8, 2017
33 tasks
@nasli nasli deleted the oauth_support branch December 12, 2017 08:55
@jesmrec jesmrec mentioned this pull request Dec 14, 2017
@nasli
Copy link
Contributor Author

nasli commented Dec 20, 2017

Related bug (36) some downloads are not downloaded after an expiration, this already happens if you lost connection or session expires, but if you select the folder as available offline all pending downloads will be retry.

@nasli
Copy link
Contributor Author

nasli commented Dec 20, 2017

Related bug (34) a queue of uploads does not retry. Within the release branch new fix has been made to relaunch all pending uploads with credentials error when the user go to the uploads view. PR: #983

@nasli
Copy link
Contributor Author

nasli commented Dec 20, 2017

Related (33) and (40) improvements will be delayed

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[UX] Make login page more intuitive Authentication based in token (OAuth2)
5 participants