7 Replies Latest reply on Jul 23, 2014 4:18 PM by JustinMaurer

    Jive iOS sdk OAuth w/  Authorization Code Grant flow

    JustinMaurer

      Does the Jive iOS SDK provide any methods to perform the OAuth authentication with an Authorization Code Grant flow?  I need to have our app users authenticate first through our SAML provider and so the Auth Code Grant flow seems the way to go.    I see the SDK has OAuthTokenWithOAuthID) that appears to only support basic authentication. 

       

      I followed the steps for Auth Code Grant flow listed here (https://community.jivesoftware.com/docs/DOC-97348) I'm able to get Jive to return an access_code to my  UIWebview after the user authenticates with our SAML idP and approves the add-on access. 


      
      
      -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
          
          NSString* urlString = [[request URL] absoluteString];
          
          if ([urlString hasPrefix:OAuth2RedirectURL]) {
              
              NSString *pageTitle = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
      
              
              NSRange tokenParam = [urlString rangeOfString: @"code="];
              if (tokenParam.location != NSNotFound) {
                  NSString* token = [urlString substringFromIndex: NSMaxRange(tokenParam)];
                  
                  // If there are more args, don't include them in the token:
                  NSRange endRange = [token rangeOfString: @"&"];
                  if (endRange.location != NSNotFound)
                      token = [token substringToIndex: endRange.location];
                  
                  NSLog(@"access token %@ %lu", token, (unsigned long)[token length]);
                  if ([token length] > 0 ) {
                      _accessCode = token;
                      
                      // Use AccessCode to obtain OAuth token
                      
                     // ?????
                      
                  
                  }
              }
              else {
                  // Handle the access rejected case here.
                  NSLog(@"rejected case, user denied request");
              }
              return NO;
          }
          return YES;
      }
      

       

      I'm having trouble getting the token though.  To manually test this i'm taking the accesscode generated from the above and running the following POST request in my browser:

       

      https://MyOAuth2ClientId:MyOAuth2ClientSecret@JiveURL?code=[_accessCode]&grant_type=authorization_code&client_id=MyOAuth2ClientId

       

      I get the following returned:

       

      {"error":"unauthorized_client","error_description":"The client failed to authorize"}

       

      I'm thinking maybe the error is due to the OAuth Add-on I have loaded is not "Full Access" does that make sense?   Any help around this greatly appreciated!


       

       

       

      Kevin Conaway Orson Bushnell

        • Re: Jive iOS sdk OAuth w/  Authorization Code Grant flow

          Hi Justin!

           

          I implemented this for a mobile app and a desktop app, so you can definitely use this and you're on the right track. I'm not using the iOS SDK though (.Net and Java in our case).

          Couple of points:

          • Your add-on does not need full access for this scenario
          • What is the JiveURL in the POST at the bottom of your post? This should be jiveUrl/oauth2/token , just making sure you are using the correct url for this
          • I have never had much success with the credentials passed to Jive in the https://username:password@jiveURL format. (Maybe I am doing something wrong). I'm always setting up a "proper" authentication header for this to work reliably
          • IIRC the parameters (code, grant type and client id) need to be passed as form parameters not query string parameters

           

          Here is my implementation of this in Java after I got the authorization code (not access code as you write) from the oauth redirect. I've stripped out some info, but hopefully it will help you a bit.

           

           

          //Get the authorization code from the OAuth redirect

               String code = query_pairs.get("code");

              

               URI jiveUri = new URI(jiveUrl);

               String url = jiveUrl +"/oauth2/token";

           

          //Create a http post using the Apache Http Client library

            HttpClient client = HttpClientBuilder.create().build();

            HttpPost post = new HttpPost(url);

            

            // add header

            post.setHeader("User-Agent", "JiveForNotes");

           

          //Setting the credentials, in this case the client id and secret

            UsernamePasswordCredentials creds = new UsernamePasswordCredentials(clientid, clientsecret);

            CredentialsProvider credsProvider = new BasicCredentialsProvider();

            credsProvider.setCredentials(

               new AuthScope(jiveUri.getHost() , AuthScope.ANY_PORT),

               creds);

           

          //Caching my credentials

            HttpHost targetHost = new HttpHost(jiveUri.getHost(), jiveUri.getPort(), jiveUri.getScheme());

            // Create AuthCache instance

            AuthCache authCache = new BasicAuthCache();

            // Generate BASIC scheme object and add it to the local auth cache

            BasicScheme basicAuth = new BasicScheme();

            authCache.put(targetHost, basicAuth);

           

           

            // Add AuthCache to the execution context

            HttpClientContext context = HttpClientContext.create();

            context.setCredentialsProvider(credsProvider);

            context.setAuthCache(authCache);

           

           

          Setting up the parameters to be passed

            List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();

            urlParameters.add(new BasicNameValuePair("code", code));

            urlParameters.add(new BasicNameValuePair("grant_type", "authorization_code"));

            urlParameters.add(new BasicNameValuePair("client_id", clientid));

           

            

            post.setEntity(new UrlEncodedFormEntity(urlParameters));

            

            HttpResponse response = client.execute(post,context);

            System.out.println("Response Code : "

                           + response.getStatusLine().getStatusCode());

           

          //OK we got back a response

           

            try {

               HttpEntity entity = response.getEntity();

               if (entity != null) {

           

          //I'm using Jackson for JSON to object mapping in this class already, so I'm lazy and will use it also to turn the response into an object

           

                    String tokenResponse = EntityUtils.toString(entity);

           

                       ObjectMapper mapper = new ObjectMapper();

                       OAuthBearerToken myToken = mapper.readValue(tokenResponse, OAuthBearerToken.class);

                       store.setValue("access_token", myToken.access_token);

                       store.setValue("refresh_token",myToken.refresh_token);

           

               }

            } finally {

              

            }

          //now I can use the token I got to set as the authorization header

            String access_token = store.getString("access_token");

            HttpGet httpget = new HttpGet(jiveUrl + "/api/core/v3/people/@me");

            httpget.setHeader("Authorization", "Bearer " + access_token);

           

            response = client.execute(httpget,context);

            System.out.println("Response Code : "

                           + response.getStatusLine().getStatusCode());

          1 person found this helpful
          • Re: Jive iOS sdk OAuth w/  Authorization Code Grant flow

            Hi, we don't provide anything in the SDK to use the code based OAuth process, as for our own Mobile 3 apps we've discontinued using that.  However, starting with our Winter '14 cloud release and version 7.0.1, we added a feature and corresponding iOS SDK code to obtain OAuth grants if you already have an authenticated session (e.g. from a session established via a SAML flow).  We use this in our official apps, so that if the feature's been enabled by the customer, the app will first authenticate with SAML and then request an OAuth token via this new mechanism.


            The method provided in the SDK to handle this:

             

            -(void) OAuthTokenWithOAuthID:(NSString*)oauthID OAuthSecret:(NSString*)oauthSecret onComplete:(void(^)(JiveOAuthCredentials*))completeBlock onError:(JiveErrorBlock)errorBlock;

             

            Once you've authenticated via SAML and have a session cookie, you can use this to obtain an OAuth grant. Then, once you get the OAuth credentials from the SDK call, you have your JiveAuthorizationDelegate start returning the JiveOAuthCredentials returned from this, and the OAuth bearer token will get applied to all your requests going forward from there. 

             

            The oauth ID and secret params to pass are the client ID and client secret from your add-on package.  You'd also want to ensure the add-on has been configured to allow the session grant functionality:

             

            • Set the Access Token and Refresh Token timeouts for the Add-on to an interval greater than the timeout settings of SAML SSO.
            • Enable Allow this add-on to obtain an access token using an authenticated session. (Enabling this setting returns a 200 status code when/api/addons/<extensionUUID>/session-grant-allowed is passed. Otherwise, this call returns a 403 error.

             

            You can use the below SDK method, with propertyName "session-grant-allowed" to confirm this configuration -- the complete block will be passed a true value if the add-on is available and configured to allow the session grant.  This is an authenticated call, so you'd need to call this after successfully setting up a session via SAML but before attempting to get an OAuth credential pair.

             

            - (void)testBooleanAddOnPropertyForName:(NSString*)propertyName forAddOnUUID:(NSString*)uuid onComplete:(void (^)(BOOL))complete onError:(JiveErrorBlock)error;

            1 person found this helpful
              • Re: Jive iOS sdk OAuth w/  Authorization Code Grant flow
                JustinMaurer
                Our production instance is currently on Jive 7.0.0.1


                Sounds like we need to upgrade to 7.0.1 to support the SAML integration.  Is it possible for the necessary mobile OAuth features to be added by support 

                With a patch?  


                I will get a local 7.0.1 instance going to try out the methods you suggest.  Thanks for all the info this really does help get a better understanding of how auth works and the direction of the mobile SDK.