16 Replies Latest reply on Apr 29, 2014 1:14 PM by dziggas

    problems with X-Jive-Run-As for external stream via add-on

    dziggas

      All,

      I'm having some trouble getting "X-Jive-Run-As" working for impersonation within a jive add-on.  Some of this is compounded by my inability to find some documentation, so I'm hoping the community can help a bit.

       

      All of this is running on a local copy of jive 7.0.0.1 so I'll include the keys/secrets here, as they don't matter.

       

      4 initial points:

      • I can't find any documentation for the required structure of the objects exchanged via the "api/jivelinks/v1/extstreams/<id>/activities" API  -- my json may simply be malformed for an impersonation request
      • The documentation Building a Jive Extension - definition.json and Core V3 API - Run-As Feature & Signed Add-Ons are conflicting on the point of what acceptable run-as strategies are, but I'm going for "username" and that seems to not be the problem.
      • Core V3 API - Run-As Feature & Signed Add-Ons indicates that "Signature will be displayed after putting in your Add-On's UUID and clicking Sign".  Neither the meta.json file nor the definition.json file have a 'uuid' field.  I've been using the id property from meta.json instead of the tile-specific id from definition.json as the tile-specific one renders a very large error in the addon upload page when used
      • I do have the following system property set:  jive.api.run_as.strategies  =  username

       

      After I get my jiveServiceSignature, the header of my definition.json looks like this:

       

      
      {
          "integrationUser": {
              "systemAdmin": true,
              "jiveServiceSignature" : "uORY+UwQ6U9hc2y+PxhvLvRYm5k=",
              "runAsStrategy" : "username"
      
      
      
      

       

      I then install my add-on, and get this response:

       

      {
        "tenantId" : "1cc35c7b-8f68-40c2-823d-9fc46d214f67-dev",
        "jiveSignatureURL" : "https://market.apps.jivesoftware.com/appsmarket/services/rest/jive/instance/validation/5fb2f0b4-854f-4a82-9485-c7d3a468708f",
        "timestamp" : "2014-04-08T02:29:34.381+0000",
        "jiveUrl" : "http://localhost:8080",
        "jiveSignature" : "gjoVeyS+qu2ixgpKwCyGgqPHMT9DiZmFLgR6/uVYlt0=",
        "scope" : "uri:/api",
        "code" : "nt5qieicddgxea9nyb7nrl0yz6r92yga.c",
        "clientSecret" : "diyowr19dkdgbotg3lufveqx8mebhw0n.s",
        "clientId" : "ieq5g5vk5ygjanjppt59mkegfuryv9it.i"
      }
      
      
      
      

       

      I then use the clientId, clientSecret, and code properties to retrieve an access token as demonstrated by the following:

       

      curl -u 'ieq5g5vk5ygjanjppt59mkegfuryv9it.i:diyowr19dkdgbotg3lufveqx8mebhw0n.s' -d 'code=nt5qieicddgxea9nyb7nrl0yz6r92yga.c&grant_type=authorization_code&client_id=ieq5g5vk5ygjanjppt59mkegfuryv9it.i' http://localhost:8080/oauth2/token
      
      
      
      

       

      The request is successful, the response is:

       

      {"scope":"uri:/api","token_type":"bearer","expires_in":"172799","refresh_token":"j03x2q4v0pv0eyfby7k51v2gviwwzzptm194r91h.r","access_token":"ec49s0nmfgtsr9ifltpfl6k1oyc5fnzw5oapcwo6.t"}
      
      
      
      

       

      I then use that access_token parameter in the following header/uri combination:

       

      http://localhost:8080/api/jivelinks/v1/extstreams/1081/activities
      X-Jive-Run-As: username myusername
      Authorization: Bearer ec49s0nmfgtsr9ifltpfl6k1oyc5fnzw5oapcwo6.t
      Content-Type: application/json
      Accept: application/json
      
      
      
      

      Where the payload is:

       

      {
        "activity" : {
          "action" : {
            "name" : "posted",
            "description" : "A Post"
          },
          "actor" : {
            "name" : "User, My",
            "email" : "my.user@email.com"
          },
          "object" : {
            "type" : "myType",
            "url" : "http://www.google.com",
            "image" : "http://localhost:9000/assets/images/wiki-48x48.png",
            "title" : "Title 605343181",
            "description" : "Comment -1113079188"
          },
          "externalID" : "172534429-1419472059"
        },
        "status" : { }
      }
      
      
      
      

       

      The response is:

       

      {
        "error" : {
          "message" : "You are not allowed to perform this request",
          "status" : 403
        }
      }
      
      
      
      

       

      This is always the response.  I've tried various combinations of the above so I thought I'd post here.  I've also tried skipping the oauth and doing Basic Auth with "admin/admin".  The result is the same 403 payload as above.  This would be my preferred method for simplicity - but at this point any guidance on either approach would be appreciated.

       

      The myusername in the X-Jive-Run-As user above matches the username of the account with the "name" and "email" properties of the actor json node above.  That account has write access to the group where the stream is installed.  If I remove the X-Jive-Run-As header from the request, the post is successful - but it is an "on behalf of" type of post, rather than appearing like the user actually made the post.

       

      Any help would be appreciated!

      Thanks!

        • Re: problems with X-Jive-Run-As for external stream via add-on
          Ryan Rutan

          Dan, I believe you get this month's ... best question detail of the month!  Absolutely amazing detail here and at a high-level this looks like you have done everything correctly.  =)

           

          While I dig into this internally, could you try something for me?  Can you try using the Run-As strategy against an official service like /contents or /places and see if it works there?

           

          I dont not think jivelinks is an official API that we are maintaining moving forward, and as such, I'm not sure if OAuth is supported on those end-points.

            • Re: Re: problems with X-Jive-Run-As for external stream via add-on
              dziggas

              Hey Ryan,

              Thanks for looking into it.

              Ryan Rutan wrote:

               

              I dont not think jivelinks is an official API that we are maintaining moving forward, and as such, I'm not sure if OAuth is supported on those end-points.

               

              When adding a stream integration to a place, this is the callback's response:

               

              {
                "code" : "kx8gixmw7idj2ca7p1d5c45778ts8s46.c",
                "name" : "conf-streams",
                "config" : {
                  "parent" : "http://localhost:8080/api/core/v3/places/1233",
                  "key" : "test1",
                  "posting" : "on"
                },
                "parent" : "http://localhost:8080/api/core/v3/places/1233",
                "url" : "http://localhost:8080/api/jivelinks/v1/extstreams/1082/activities",
                "guid" : "community:localhost%3A8080/extstream:1082",
                "tenantID" : "1cc35c7b-8f68-40c2-823d-9fc46d214f67-dev",
                "placeUri" : "http://localhost:8080/api/core/v3/places/1233",
                "jiveUrl" : "http://localhost:8080",
                "id" : 1082
              }
              

               

              If you notice the url property here (line 10), this is what Jive sends back, so if it's not supported... please let me know (and let your devs know!), as we'd have to rewrite that after receiving the response.

               

              In addition, this is the API that the jive-sdk uses via:

               

              jive-sdk create activity --name=whatever
              

               

              I believe the SDK uses oauth via Node, right?

               

              If there is a newer/supported API for writing external activities, can you point me to that doc?

              Ryan Rutan wrote:

               

              Can you try using the Run-As strategy against an official service like /contents or /places and see if it works there?

               

              Yup, I'll try to whip that up shortly.

               

              Thanks!

                • Re: Re: Re: problems with X-Jive-Run-As for external stream via add-on
                  dziggas

                  Hey Ryan, this worked just fine via the /content api:

                   

                  curl -H "Authorization: Bearer b1wdq9l9snskniorrp1zy2pnoueahgmkedi6oi94.t" -H "Content-Type: application/json" -H "X-Jive-Run-As: username myuser" --data '{"content": { "type": "text/html", "text": "<body><p>Some interesting text to discuss</p></body>" }, "subject": "New Discussion", "type": "discussion" }' http://localhost:8080/api/core/v3/places/1233/contents
                  

                   

                  (the access token is not the same as above, but it was acquired the same way).

                   

                  Any ideas?  Is impersonation not supported for external streams (that would be a HUGE bummer).

                   

                  Thanks,

                  Dan

                    • Re: problems with X-Jive-Run-As for external stream via add-on
                      Ryan Rutan

                      Impersonation should be supported for any v3 API, the only questions have outstanding is if it is supposed to work for jivelinks or why other service that is not v3.

                        • Re: problems with X-Jive-Run-As for external stream via add-on

                          The "Run As" support works for V3, V2, and JiveLinks.

                            • Re: Re: problems with X-Jive-Run-As for external stream via add-on
                              dziggas

                              Hmm, so does that mean my json POST body is wrong in some way?  I haven't been able to find doc describing each element of the activity object expected by api/jivelinks/v1/extstreams and/or the activity's nested objects.

                               

                              For example, is the actor node still required if the actor is to be inferred by the Run-As header?

                               

                              "actor" : {  
                                    "name" : "User, My",  
                                    "email" : "my.user@email.com"  
                                  }
                              
                              

                               

                              Otherwise, is there some logging package that I could enable that would log on the server the reason for dispatching a 403?

                                • Re: problems with X-Jive-Run-As for external stream via add-on
                                  Ryan Rutan

                                  Dan, jiveLinks is a legacy API and one that we support/document moving forward.   Craig McClanahan given this, it looks like Dan is being given a v1/jivelinks api resource for his activity stream.  Assuming that this is something that will be updated to V3 eventually, but is there a V3 supplement he can use in the mean time?

                                    • Re: Re: problems with X-Jive-Run-As for external stream via add-on
                                      dziggas

                                      Hi Craig McClanahan Ryan Rutan any input on this?  If we're stumped here, I can move this discussion to my organizations space and convert to a L3 support Case - just let me know!

                                       

                                      While Craig seemed to indicate that the jivelinks API supported impersonation.  Despite that, I tried finding the right v3 API and attempted both:

                                       

                                      /api/core/v3/activities

                                      /api/core/v3/places/<my group>/contents

                                       

                                      Via the /activities resource, I couldn't get the activity to be 'hooked' into my external stream specifically.  It just floated in the general activity stream for the user, despite attempting to nudge the API in the right direction with an activity that models:

                                       

                                      {
                                        "action" : {
                                          "name" : "posted",
                                          "description" : "A Post"
                                        },
                                        "actor" : {
                                          "name" : "User, My",
                                          "email" : "my.user@email.com"
                                        },
                                        "object" : {
                                          "type" : "custom",
                                          "url" : "http://www.google.com",
                                          "image" : "http://localhost:9000/assets/images/wiki-48x48.png",
                                          "title" : "Title 521397337",
                                          "description" : "Comment 1746154618"
                                        },
                                        "title" : "someTitle",
                                        "content" : "someBody",
                                        "type" : "extStreamActivity",              <---- this didn't do anything
                                        "externalStreamID" : 1096,                  <---- this didn't do anything
                                        "externalID" : "-1331337620269991235"
                                      }
                                      

                                       

                                      The /contents resource just returned:

                                       

                                      {
                                        "error" : {
                                          "message" : "External Stream Activity cannot be created through the /contents endpoint",
                                          "status" : 400
                                        }
                                      }
                                      

                                       

                                      ... so it identified my chicanery and denied me.

                                       

                                      So, I'm a bit at a loss.

                                      Is there a replacement for /jivelinks I should use?  If so what is it?

                                      If there isn't a replacement for /jivelinks - how can I identify why my original impersonation request is giving me a 403?

                                       

                                      I can download the source and attach a debugger - but I was really hoping to avoid that

                                       

                                      Thanks!

                                        • Re: Re: problems with X-Jive-Run-As for external stream via add-on
                                          Ryan Rutan

                                          Dan Ziggas - Talked to a few people in engineering and one question came up that I couldn't answer.   could you explain the need to generate the activity with impersonation?  My understanding of this API (granted I haven't looked at it close for a while), was that if you declare the Actor then you dont need impersonation?  The question I need to find out is if Actor is mutable.  If so, then I would recommend trying without impersonation.

                                           

                                          I'm going to reach out  to see if we can give you a functioning snippet to help with your efforts.  If I were to sum up your requirements, you basically need to create raw activity for your external stream source, or is there something more complex I'm missing here?

                                            • Re: Re: problems with X-Jive-Run-As for external stream via add-on
                                              dziggas

                                              Ryan Rutan awesome question - I should have led with this to make sure my assumptions are correct.

                                               

                                              We want to use Purposeful Places to let users make groups that can have stream integrations with other internal systems.  So we need to be able to pump activity into those streams via the add-on.  When these activities pop in the stream, we want them to look like any other jive activity.  Here is a non-impersonated Activity entry from the integration which is uncleverly named Streams, followed by an impersonated discussion posted via the above API call at your suggestion:

                                               

                                              g3.png

                                               

                                              The mentioning of the integration name (Streams), as well as the "posted on behalf of" bit causes a bit of cognitive dissonance which we'd like to avoid, but the real problem is that the Ziggas entry (which is the title of the external Activity) insertion into the external stream does not register as Activity initiated by that user for the purposes of following that user in a custom stream, nor for viewing that user's activity from their Profile.

                                               

                                              Are my expectations correct in that the above should be possible for external Activity in the same manner that it is possible for jive content types?

                                               

                                              Appreciate all hints!

                                               

                                                • Re: problems with X-Jive-Run-As for external stream via add-on
                                                  Ryan Rutan

                                                  Based on what I've seen I do not think you can create raw activity inside a group, but rather activity with attribution.  I now get the need for the Run-As, but I believe we are hitting an edge case here.  When a Jive extstream integration registers with Jive, it creates a finally scoped integration user for that place, and adding Run-As to that scope doesn't work because that integration user will never have the right permissions.

                                                   

                                                  To move forward on this, the best option you have is to either "sign" your add-on, similar to the steps in:

                                                  Core V3 API - Run-As Feature & Signed Add-Ons

                                                  such that you can get an add-on level integration user that is Full Access, and create the activity using that user with the Run-As capabilities.  Instead of using the integration user created by the Tile, you would use this add-on integration user which is properly scoped to do Run-As against the Tile end-points for creating activity.

                                                   

                                                  This is WAY overkill IMO, but it is the only way that you can affectively use the Run-As in the manner you wanting.  Sorry for the delay here, let me know if that doesn't work.

                                                    • Re: problems with X-Jive-Run-As for external stream via add-on
                                                      dziggas

                                                      Hey Ryan Rutan thanks for the reply - a question:

                                                      Ryan Rutan wrote:

                                                       

                                                      To move forward on this, the best option you have is to either "sign" your add-on, similar to the steps in:

                                                      Core V3 API - Run-As Feature

                                                      such that you can get an add-on level integration user that is Full Access, and create the activity using that user with the Run-As capabilities.  Instead of using the integration user created by the Tile, you would use this add-on integration user which is properly scoped to do Run-As against the Tile end-points for creating activity.

                                                       

                                                      I think this is what I already tried prior to posting my original question.  Can you explain how the steps would differ between signing the addon and using the integration user vs using the tile user?  My original steps listed at the very top of this thread were just following the steps in Core V3 API - Run-As Feature so I'm curious which step I should altar.

                                                       

                                                      Thanks!