Skip to end of metadata
Go to start of metadata

Available:

Crowd 2.1 and later.

API version:

1

Note that these might be out of date. For the current versions of Crowd see https://docs.atlassian.com/atlassian-crowd/latest/REST/

 

The Crowd REST APIs allow you to address the Crowd data entities as 'resources'. This means that the data entities are identified by URIs and operated on by HTTP requests (GET, POST, PUT and DELETE). Whenever you GET one of these resources, you receive a representation encoded in XML or JSON. Below are details of the resources made available by the APIs.

On this page:

Overview

Crowd offers a set of REST APIs for use by applications connecting to Crowd.

Please note the main difference between Crowd APIs and the APIs of other applications like JIRA and Confluence: In Crowd, an application is the client of Crowd, whereas in JIRA/Confluence a user is the client. For example, when authenticating a request to a Crowd REST resource via basic authentication, the application name and password is used (and not a username and password). Keep this in mind when using the REST APIs.

URIs for a Crowd REST API resource have the following structure:
With context:

http://host:port/context/rest/api-name/api-version/resource-name

Or without context:

http://host:port/rest/api-name/api-version/resource-name

API Name - usermanagement

In Crowd 2.1, the only api-name available is usermanagement. This is the API that allows an application to interact with the Crowd server.

Examples

With context:

http://myhost.com:8095/crowd/rest/usermanagement/1/user?username=USERNAME
http://localhost:8095/crowd/rest/usermanagement/latest/user?username=USERNAME

Or without context:

http://crowd.myhost.com:8095/rest/usermanagement/1/user?username=USERNAME
http://crowd.myhost.com:8095/rest/usermanagement/latest/user?username=USERNAME

Please refer to the Crowd REST API usage guide for a description of the common factors in the APIs, including a full explanation of the URI format, authentication, API versions, HTTP response codes, and so on.

User Resource

Figure 1: User
<?xml version="1.0" encoding="UTF-8"?>
  <user name="username" expand="attributes">
  <first-name>First</first-name>
  <last-name>Last</last-name>
  <display-name>First Last</display-name>
  <email>email@email.com</email>
  <active>true</active>
  <attributes>
    <link rel="self" href="link_to_user_attributes"/>
  </attributes>
  <password>
    <link rel="edit" href="link_to_user_password"/> <!-- /user/password?username=<username> -->
    <value>password</value> <!-- only used when creating a user, otherwise not filled in -->
  </password>
</user>
User List
<?xml version="1.0" encoding="UTF-8"?>
<users expand="user">
  <user name="username">
    <link rel="self" href="link_to_user"/>
  </user>
</users>

Request Body (XML)

Description

Status Code

Response Body (XML)

None.

GET /user?username=USERNAME

 

Retrieves a user

200 (OK) if the user exists
404 (Not Found) if the user could not found

As in Figure 1

None.

GET /user?username=USERNAME&expand=attributes

 

Retrieves a user with attributes

200 (OK) if the user exists
404 (Not Found) if the user could not be found

As in Figure 1 with attributes filled in

As in Figure 1, except with a password element

POST /user

 

Creates a new user

201 (Created) if the user is successfully created
400 (Bad Request) if the user password is left out or user already exists
403 (Forbidden) if the application is not allowed to create a new user

(Since Crowd 2.8)

As in Figure 1 with attributes filled in.

As in Figure 1, except with a password element

PUT /user?username=USERNAME

 

Updates a user

204 (No Content) if the user previously existed and is now updated
400 (Bad Request) if the usernames in the request body and the URI do not match
403 (Forbidden) if the application is not allowed to update/create a user
404 (Not Found) if the user does not exist

As in Figure 1

None.

DELETE /user?username=USERNAME

 

Deletes a user

204 (No Content) if the user is found and deleted
403 (Forbidden) if the application is not allowed to delete the user
404 (Not Found) if the user could not be found

 

None.

GET /user/attribute?username=USERNAME

 

Retrieves a list of user attributes

200 (OK) if the user exists
404 (Not Found) if the user could not be found

A list of user attributes

<?xml version="1.0" encoding="UTF-8"?>
<attributes>
  <attribute name="fruit">
    <values>
      <value>orange</value>
      <value>apple</value>
    </values>
  </attribute>
</attributes>

POST /user/attribute?username=USERNAME

 

Stores all the user attributes for an existing user

204 (No Content) if the user attributes are successfully set
403 (Forbidden) if the application is not allowed to set user attributes
404 (Not Found) if the user could not be found

 

None.

DELETE /user/attribute?username=USERNAME&attributename=ATTRIBUTENAME

 

Deletes a user attribute

204 (No Content) if the user attribute is successfully deleted or the attribute was not defined for the user
403 (Forbidden) if the application is not allowed to remove a user attribute
404 (Not Found) if the user could not be found

 

<?xml version="1.0" encoding="UTF-8"?>
<password>
  <value>new-password</value>
</password>

PUT /user/password?username=USERNAME

 

Updates a user's password

204 (No Content) if the password is successfully updated
403 (Forbidden) if the application is not allowed to update a user's password
404 (Not Found) if the user could not be found

 

None.

POST /user/mail/password?username=USERNAME

 

Sends the user a password reset link

204 (No Content) if the user is found
403 (Forbidden) if the application is not allowed to send the user a reset password link
404 (Not Found) if the user could not be found

 

None.

POST  /user/mail/usernames?email=EMAIL

 

Sends a username reminder to the users associated with the given email address

204 (No Content) if successful
403 (Forbidden) if the application is not allowed to send the user a username reminder
404 (Not Found) if the user could not be found

 

None.

GET /user/group/direct?username=USERNAME

Optional start-index and max-results query params


 Retrieves the groups that the user is a direct member of

200 (OK) if the user is found, otherwise 404 (Not Found)

List of groups (See Group List figure)

None.

GET /user/group/direct?username=USERNAME&groupname=GROUPNAME

 

Retrieves the group that the user is a direct member of

200 (OK) if the user and group are found, otherwise 404 (Not Found)

See Group List figure

<?xml version="1.0" encoding="UTF-8"?>
<group name="groupname"/>

POST /user/group/direct?username=USERNAME

 

Adds the user (USERNAME) as a direct member of the group (GROUPNAME)

201 (Created) if the user is successfully added to the group
400 (Bad Request) if the group could not be found
403 (Forbidden) if the application is not allowed to add the group membership
404 (Not Found) if the user cannot be found 
409 (Conflict) if the user is already a direct member of the group

 

None

DELETE /user/group/direct?username=USERNAME&groupname=GROUPNAME

 

Removes the group membership of the user

204 (No Content) if the group membership is successfully deleted
403 (Forbidden) if the application is not allowed to delete the group membership
404 (Not Found) if the user or group could not be found

 

None

GET /user/group/nested?username=USERNAME

Optional start-index and max-results query params


Retrieves the groups that the user is a nested member of

200 (OK) if the user is found, otherwise 404 (Not Found)

List of groups (See Group List figure)

None

GET /user/group/nested?username=USERNAME&groupname=GROUPNAME

 

Retrieves the group that the user is a nested member of

200 (OK) if the user and group are found, otherwise 404 (Not Found)

See Group List figure

Group Resource

Figure 2: Group
<?xml version="1.0" encoding="UTF-8"?>
<group name="groupname" expand="attributes">
  <type>GROUP</type>
  <description>Group Description</description>
  <active>true</active>
  <attributes>
    <link rel="self" href="link_to_group_attributes"/>
  </attributes>
</group>
Group List
<?xml version="1.0" encoding="UTF-8"?>
<groups expand="group">
  <group name="groupname">
    <link rel="self" href="link_to_group"/>
  </group>
</groups>
All Group Memberships
<memberships>
 <membership group='parent-group'>
  <users>
   <user name='parent-group-user'/>
   ...
  </users>
  <groups>
   <group name='child-group'/>
   ...
  </groups>
 </membership>
 ...
</memberships>

Request Body (XML)

Description

Status Code

Response Body (XML)

None.

GET /group?groupname=GROUPNAME

 

Retrieves a group

200 (OK) if the group is found, otherwise 404 (Not Found)

As in Figure 2

None.

GET /group?groupname=GROUPNAME&expand=attributes

 

Retrieves a group with attributes

200 (OK) if the group is found, otherwise 404 (Not Found)

As in Figure 2 except including a list of group attributes

As in Figure 2

POST /group

 

Creates a new group

201 (Created) if the group is successfully created
400 (Bad Request) if the group already exists
403 (Forbidden) if the application is not allowed to create a new group

 

As in Figure 2

PUT /group?groupname=GROUPNAME

 

Updates a group

200 (OK) if the group previously existed and is now updated
400 (Bad Request) if the groupname in the request body and the URI do not match
403 (Forbidden) if the application is not allowed to update/create a group
404 (Not Found) if the group does not exist

As in Figure 2

None.

DELETE /group?groupname=GROUPNAME

 

Deletes a group

204 (No Content) if the group is found and deleted
404 (Not Found) if the group could not be found

 

None.

GET /group/attribute?groupname=GROUPNAME

 

Retrieves a list of group attributes

200 (OK) if the group attribute is found, otherwise 404 (Not Found)

A list of group attributes

None

POST /group/attribute?groupname=GROUPNAME

 

Stores all the group attributes

204 (No Content) if the group attributes are successfully set
403 (Forbidden) if the application is not allowed to set group attributes
404 (Not Found) if the group could not be found

 

None

DELETE /group/attribute?groupname=GROUPNAME&attributename=ATTRIBUTENAME

 

Deletes a group attribute

204 (No Content) if the group attribute is successfully deleted
403 (Forbidden) if the application is not allowed to remove a group attribute
404 (Not Found) if the group or attribute could not be found

 

Optional start-index and max-results query params

GET /group/user/direct?groupname=GROUPNAME

 

Retrieves the users that are direct members of the specified group

200 (OK) if the group is found, otherwise 404 (Not Found)

List of users

<?xml version="1.0" encoding="UTF-8"?>
<user name="username"/>

POST /group/user/direct?groupname=GROUPNAME

 

Adds user as direct member of group

201 (Created) if the user is successfully added as a member of the group
400 (Bad Request) if the user could not be found
404 (Not Found) if the group could not be found 
409 (Conflict) if the user is already a direct member of the group

 

None

GET /group/user/direct?groupname=GROUPNAME&username=USERNAME

 

Retrieves the user that is a direct member of the specified group

200 (OK) if the group and user are found, otherwise 404 (Not Found)

See User figure

None

DELETE /group/user/direct?groupname=GROUPNAME&username=USERNAME

 

Removes the user membership

204 (No Content) if the user membership is successfully deleted
404 (Not Found) if the user or group could not be found

 

None.

GET /group/user/nested?groupname=GROUPNAME

Optional start-index and max-results query params


Retrieves the users that are nested members of the specified group

200 (OK) if the group is found, otherwise 404 (Not Found)

List of users

None.

GET /group/user/nested?groupname=GROUPNAME&username=USERNAME

 

Retrieves the user that is a nested member of the specified group

200 (OK) if the group and user are found, otherwise 404 (Not Found)

See User figure

None.

GET /group/parent-group/direct?groupname=GROUPNAME

Optional start-index and max-results query params


Retrieves the groups that are direct parents of the specified group

200 (OK) if the group is found, otherwise 404 (Not Found)

List of groups

<?xml version="1.0" encoding="UTF-8"?>
<group name="parent-group-name"/>

POST /group/parent-group/direct?groupname=GROUPNAME

 

Adds a direct parent group membership

201 (Created) if the parent group membership is successfully added
400 (Bad Request) if the parent group could not be found, or adding the membership would result in a circular dependency
404 (Not Found) if the group could not be found

 

None.

GET /group/parent-group/direct?groupname=GROUPNAME&parent-groupname=PARENT-GROUPNAME

 

Retrieves the group that is a direct parent of the specified group

200 (OK) if the groups are found, otherwise 404 (Not Found)

See Group List figure

None.

GET /group/parent-group/nested?groupname=GROUPNAME

Optional start-index and max-results query params

 

Retrieves the groups that are nested parents of the specified group

200 (OK) if the group is found, otherwise 404 (Not Found)

List of groups

None

GET /group/parent-group/nested?groupname=GROUPNAME&parent-groupname=PARENT-GROUPNAME

 

Retrieves the group that is a nested parent of the specified group

200 (OK) if the groups are found, otherwise 404 (Not Found)

See Group figure

None

GET /group/child-group/direct?groupname=GROUPNAME

Optional start-index and max-results query params

 

Retrieves the groups that are direct children of the specified group

200 (OK) if the group is found, otherwise 404 (Not Found)

List of groups (See Group List figure)

<?xml version="1.0" encoding="UTF-8"?>
<group name="child-group-name"/>

POST /group/child-group/direct?groupname=GROUPNAME

 

Adds a direct child group membership

201 (Created) if the child group membership is successfully added
400 (Bad Request) if the child group could not be found, or adding the membership would result in a circular dependency
404 (Not Found) if the group could not be found

 

None.

GET /group/child-group/direct?groupname=GROUPNAME&child-groupname=CHILD-GROUPNAME

 

Retrieves the group that is a direct child of the specified group

200 (OK) if the groups are found, otherwise 404 (Not Found)

See Membership figure

None.

DELETE /group/child-group/direct?groupname=GROUPNAME&child-groupname=CHILD-GROUPNAME

 

Deletes a child group membership

204 (No Content) if the child group membership is deleted
404 (Not Found) if the child or parent group could not be found

 

None.

GET /group/child-group/nested?groupname=GROUPNAME

Optional start-index and max-results query params


Retrieves the groups that are nested children of the specified group

200 (OK) if the group is found, otherwise 404 (Not Found)

List of groups (See Group List figure)

None.

GET /group/child-group/nested?groupname=GROUPNAME&child-groupname=CHILD-GROUPNAME

 

Retrieves the group that is a nested child of the specified group

200 (OK) if the groups are found, otherwise 404 (Not Found)

See Group figure

 

GET /group/membership

 

Retrieves full details of all group memberships, with users and nested groups.
200 (OK) on success, or 404 if unavailable in earlier releases of Crowd.

Membership details for every group. See All Group Memberships figure. This resource is optimised for streaming XML responses, and does not support JSON responses.

User Authentication Resource

No session is created in user authentication. An application can simply ask Crowd "is this username/password valid?" This is the primary purpose of the Authentication resource.

Successful Authentication Response
<?xml version="1.0" encoding="UTF-8"?>
<user name="username">
  ...
</user>
Unsuccessful Authentication Response
<?xml version="1.0" encoding="UTF-8"?>
<error>
  <reason>...</reason>
  <message>Error message</message>
</error>
 

Request Body (XML)

Description

Status Code

Response Body (XML)

<?xml version="1.0" encoding="UTF-8"?>
<password>
  <value>Password</value>
</password>

POST /authentication?username=USERNAME

 

Authenticates a user

200 (OK) if successful
400 (Bad Request) if unsuccessful

As below

Search Resource

All Search resource methods have optional start-index and max-results query params.

Request Body (XML)

Description

Status

<?xml version="1.0" encoding="UTF-8"?>
<property-search-restriction>
  <property>
    <name>email</name>
    <type>STRING</type>
  </property>
  <match-mode>EXACTLY_MATCHES</match-mode>
  <value>bob@example.net</value>
</property-search-restriction>

POST /search?entity-type=user

 

Searches for users (returning the usernames) with the specified search restriction

 

As above

POST /search?entity-type=user&expand=user

 

Searches for users with the specified search restriction

 

As above

POST /search?entity-type=group

 

Searches for groups (returning the group names) with the specified search restriction

 

As above

POST /search?entity-type=group&expand=group

 

Searches for groups with the specified search restriction

 

From Crowd 2.2 onwards, you can perform searches using the Crowd Query Language. Use a GET, rather than a POST, and provide the restriction parameter with CQL:

As above

GET /search?entity-type=ENTITY_TYPE&restriction=CQL_QUERY

 

Searches for entities of ENTITY_TYPE (either 'user' or 'group') with the specified search restriction (as Crowd Query Language).

 

Crowd SSO Token Resource

The Crowd SSO token resource allows an application to authenticate a user and receive an SSO token from the Crowd server. The application decides what to do with the SSO token, though normally this SSO token is set as a cookie in the user's browser.

Crowd SSO Session
<?xml version="1.0" encoding="UTF-8"?>
<session expand="user">
  <link rel="self" href="link_to_token_URI"/>
  <token>abc123</token>
  <user name="username"/> <!-- authenticated user -->
  <created-date>2013-01-30T16:38:27.369+11:00</created-date>
  <expiry-date>2013-01-30T17:08:27.369+11:00</expiry-date>
</session>
Unsuccessful Crowd SSO Session Creation Response
<?xml version="1.0" encoding="UTF-8"?>
<error>
  <reason>...</reason>
  <message>Error message</message>
</response>

Request Body (XML)

Description

Status

Response Body (XML)

<?xml version="1.0" encoding="UTF-8"?>
<authentication-context>
  <username>my_username</username>
  <password>my_password</password>
  <validation-factors>
    <validation-factor>
      <name>remote_address</name>
      <value>127.0.0.1</value>
    </validation-factor>
  </validation-factors>
</authentication-context>

POST /session

Optional validate-password and duration query params

 

Create new session token valid for duration seconds, or for the server default session timeout if no duration is specified or if duration is longer than the server default session timeout

Either user password needs to be valid or validate-password query param must be set to false

If an ongoing session already exists for the same authentication credentials and validation factors, then that session token is returned.

201 (Created) with successful response as above if the session creation was successful or an ongoing session already existed
400 (Bad Request) with unsuccessful response as above if the user authentication details are incorrect (e.g., bad password, inactive user, user does not have permission to authenticate with the application).

See Crowd SSO Session entity above

None.

DELETE /session?username=USERNAME

Optional exclude query param

 

Invalidate all tokens for a given user name.

Optionally, a token key can be saved from invalidation if specified in the exclude param

204 (No Content) if successful

404 (Not Found) if the user is not found

400 (Bad request) if the application is not found

 

None.

GET /session/{token}

 

Retrieves the token with the authenticated user expanded

200 (OK) if successfully retrieved
404 (Not Found) if the token is not found

See Crowd SSO Session entity above

<?xml version="1.0" encoding="UTF-8"?>
<validation-factors>
  <validation-factor>
    <name>remote_address</name>
    <value>127.0.0.1</value>
  </validation-factor>
</validation-factors>

POST /session/{token}

 

Validates the session token. Validating the token keeps the SSO session alive.

200 (OK) if successful
400 (Bad request) if the validation factors are incorrect
404 (Not Found) if the token cannot be found

See Crowd SSO Session entity above

 

DELETE /session/{token}

 

Invalidates the token

204 (No Content)

 

Cookie Configuration Resource

GET /config/cookie

Description

Status

Response Body (XML)

Retrieves cookie configurations

200 (OK)

<?xml version="1.0" encoding="UTF-8"?>
<cookie-config>
  <domain>.atlassian.com</domain>
  <secure>true</secure>
  <name>cookie-name</name>
</cookie-config>
RELATED TOPICS

Overview of the Crowd REST APIs
Crowd Developer Documentation

<memberships>
 <membership group='parent-group'>
  <users>
   <user name='parent-group-user'/>
   ...
  </users>
  <groups>
   <group name='child-group'/>
   ...
  </groups>
 </membership>
 ...
</memberships>

 

47 Comments

  1. Unknown User (vanolst@rii.ricoh.com)


    I'm wondering how retrieving a session token differs from validating it. (GET /session/token vs POST /session/token)

    Can someone elaborate?

    1. Validating the token keeps the SSO session alive. I'll update the documentation to reflect this.

      1. Unknown User (vanolst@rii.ricoh.com)

        James, 

        Thanks for the helpful reply.

        Next question then:  I am evaluating Atlassian Crowd Version: 2.1.0-beta4 (Build:#430 - 15-11-2010) (and I am glad to see that the REST interface was released out of beta, but I have not installed it yet).

        I have several sessions I have created with POST /session.   As seen from the Session Browser, I now have several of these User Sessions that are a couple of days old! Timeout setting is the default 30 minutes.

        Question 1:  Is there a bug, or does the token actually have to be challenged somehow to make it expire?

        Question 2: Why would I need to validate a session to keep it alive if seems to hang around if I do nothing?

        I'm sure I am just looking at this wrong somehow.

        Thanks

        Dan

        1. Hi Daniel,

          Yup, the token has to be challenged for it to expire. As soon as you use the token, Crowd will notice that the token has expired and remove it. It will then return a 400 (Bad Request) status with an error reason of "INVALID_SSO_TOKEN".  So even though the token hangs around, it will be removed as soon as it is used.

          I hope this answers both your questions.

          Regards,

          James

  2. Unknown User (avdd@careflight.org)

    Is it possible to use JSON for the request body?

    1. Yup, JSON works for both the request and the response. Just ensure that you set the correct "Content-Type" and "Accept" headers.

      1. Unknown User (avdd@careflight.org)

        So, how do I format it?

        1. For example, if you were using the authentication resource, the POST body would look like:

          

          { "value": "password" }
          

          So the cURL command would be:

          curl -X POST -H "Accept: application/json" -H "Content-Type: application/json" -u appname:apppassword -d '{"value":"password"}' http://localhost:8095/crowd/rest/usermanagement/1/authentication?username=USERNAME
          
          1. Unknown User (avdd@careflight.org)

            And are we meant to determine on our own the rest of the messages, or is there some deterministic way to convert the XML messages to JSON, or perhaps even a list of these somewhere?

  3. Anonymous

    Hi, could you please add a JSON example for authentication?

    Also, I am wondering if I need to set up anything to make the the REST api available? ...most likely I haven't figured out the correct url to use yet =)

  4. Unknown User (avdd@careflight.org)

    I'll just leave this here:

    <?xml version="1.0" encoding="UTF-8"?>
    <validation-factors>
      <validation-factor>
        <name>remote_address</name>
        <value>127.0.0.1</value>
      </validation-factor>
    </validation-factors>
    

    becomes:

    {"validationFactors": [{"name": "remote_address", "value": "127.0.0.1"}]}
    

    Obvious, isn't it?

  5. Anonymous

    Hello!

    Can any one please post the latest JSON formats of the request bodies for the SSO Token Resource along with the validation factors?.

    The above comments don't have the whole body.

    Am using: {"authentication-context":{"username":"my_username","password":"my_password","validation-factors":{"validation-factor":{"name":"remote_address","value":"127.0.0.1"}}}}

    C:\>curl -X POST -T ssopost.txt -u ebam:wallstreet -H "Accept: application/json" -H "Content-Type: application/json" "http://crl***01.w**ms.com:8095/crowd/rest/usermanagement/1/session"

    Unknown macro: {"status-code"}

    This works fine: 

    Unknown macro: {"username"}

    Cheers!

    Nirav

    <?xml version="1.0" encoding="UTF-8"?>
    <authentication-context>
      <username>my_username</username>
      <password>my_password</password>
      <validation-factors>
        <validation-factor>
          <name>remote_address</name>
          <value>127.0.0.1</value>
        </validation-factor>
      </validation-factors>
    </authentication-context>

  6. Anonymous

    Hello!

    Can any one please post the latest JSON formats of the request bodies for the SSO Token Resource along with the validation factors?.

    The above comments don't have the whole body.

    Am using: 

    {"authentication-context":{"username":"my_username","password":"my_password","validation-factors":{"validation-factor":{"name":"remote_address","value":"127.0.0.1"}}}}
    
    C:\>curl -X POST -T ssopost.txt -u ebam:wallstreet -H "Accept: application/json" -H "Content-Type: application/json" "http://crl****01.w***ms.com:8095/crowd/rest/usermanagement/1/session"
    
    {"status-code":500,"message":"Unrecognized field \"authentication-context\" (Class com.atlassian.crowd.plugin.rest.entity.AuthenticationContextEntity), not marked as ignorable\n at [Source: org.apache.catalina.connector.CoyoteInputStream@709438dd; line: 1, column: 2]"}
    

    This works fine: 

    {"username":"my_username","password":"my_password"}
    

    Cheers!

    Nirav

    <?xml version="1.0" encoding="UTF-8"?>
    <authentication-context>
      <username>my_username</username>
      <password>my_password</password>
      <validation-factors>
        <validation-factor>
          <name>remote_address</name>
          <value>127.0.0.1</value>
        </validation-factor>
      </validation-factors>
    </authentication-context>

  7. Anonymous

    Just some additional info for the above comment. The below doesn't work as well !

    {"validationFactors":[{"name":"remote_address","value":"10.100.135.31"}],"username":"test1","password":"test1234"}
    
    C:\>curl -X POST -T ssopost.txt -u ebam:wallstreet -H "Accept: application/json" -H "Content-Type: application/json" "http://c******1.wl*********s.com:8095/crowd/rest/usermanagement/1/session"
    
    {"status-code":500,"message":"Unrecognized field \"validationFactors\" (Class com.atlassian.crowd.plugin.rest.entity.AuthenticationContextEntity), not marked as ignorable\n at [Source: org.apache.catalina.connector.CoyoteInputStream@2e2a1a92; line: 1, column: 2]"}
    
  8. For all asking about the JSON format, we will update the above documentation to give more examples. Unfortunately the conversion is not quite as straight forward as we'd like. I will give the below examples and hopefully that should get you started on what you need.

    For creating a new session token:
    

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <authentication-context>
        <username>username</username>
        <password>password</password>
        <validation-factors>
            <validation-factor>
                <name>factor1</name>
                <value>value1</value>
            </validation-factor>
            <validation-factor>
                <name>factor2</name>
                <value>value2</value>
            </validation-factor>
        </validation-factors>
    </authentication-context>
    

    converts to

    {"username":"username",
     "password":"password",
     "validation-factors": {
            "validationFactors":[{"name":"factor1", "value":"value1"},
                                 {"name":"factor2", "value":"value2"}]}
    }
    

    For validating a token:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <validation-factors>
        <validation-factor>
            <name>factor1</name>
            <value>value1</value>
        </validation-factor>
        <validation-factor>
            <name>factor2</name>
            <value>value2</value>
        </validation-factor>
    </validation-factors>
    

    converts to

    {"validationFactors":[{"name":"factor1","value":"value1"},
                          {"name":"factor2","value":"value2"}]}
    

    Hope that helps, and apologies for the delay in replying.

  9. Unknown User (circusdog)

    Correction:  a PUT to /user?username=USERNAME to update a user returns a 204, not a 200.

  10. Anonymous

    Several of the methods in Group Resource have "See Membership figure" in Response Body (XML).  I don't see the membership figure anywhere, am I blind?

    1. Thanks for pointing that out - I've fixed up the documentation.

  11. Anonymous

    I am i a
    I am getting a 404  using this request...

    curl -X POST -H "Accept: application/xml" -H "Content-type: application/xml" -u jira:jira  -d '<?xml version="1.0" encoding="UTF-8"?>
      <user name="changeme@test.com" expand="attributes">
      <first-name>first name</first-name>
      <last-name>last name</last-name>
      <display-name>disp name</display-name>
      <email>changeme@test.com</email>
      <active>true</active>
      <attributes>
        <link rel="self" href="link_to_user_attributes"/>
      </attributes>
      <password>
        <link rel="edit" href="link_to_user_password">
        <value>test</value>
      </password>
    </user> '   http://test.org/rest/usermanagement/1/user

    can you please help me...

    1. Could you try the cURL command again with an extra "-v" parameter which stands for "verbose". I'm just concerned that you aren't actually hitting a Crowd server. In the output, you should be able to see some extra custom headers that will reveal whether you are talking to a Crowd server. Look for "Embedded-Crowd-Version" in the headers. If you don't see it, you have the wrong URL.

    2. Anonymous

      I was also getting a 400 code response and it drove me insane for about 3 hours ;-)

      Figure 1 is missing a forward slash, so change this: 

      <link rel="edit" href="link_to_user_password">
      

      to this: 

      <link rel="edit" href="link_to_user_password"/>
      
  12. Anonymous

    Would it be possible to get the JSON format for the Search Resource Request Body?  I've tried to guess based on the SSO Token format but I'm having no luck.

    1. Hi,

      For searching, it might be easier just to use the Crowd Query Language to perform the search. This is simply a GET request and doesn't require you to know the format of the request body. In particular, have a look at the list of fields we support.

      Just a reminder that the query parameters must be URL encoded. So for example you can perform a search by doing a GET on:

      http://myhost.com:8095/rest/usermanagement/1/search?entity-type=user&restriction=email%3Dbob%40example.net
      

      Would love feedback on it.

      1. Anonymous

        What would you do if you wanted to search for an attribute value rather than one of the CQL supported fields using JSON? You can search for attribute values using XML but this doesn't seem to be supported by the CQL. Using the above Search Resource the XML looks like this:

        <property-search-restriction>
         <property>
           <name>myattribute</name>
           <type>STRING</type>
         </property>
         <match-mode>EXACTLY_MATCHES</match-mode>
         <value>myvalue</value>
        </property-search-restriction>
        

        and returns users with the correct attribute. How would this be structured for JSON?

  13. Anonymous

    The format for the request body for POST /user/attribute?username=USERNAME is needed on this page.   (One can guess the format, but it would be helpful if it were explicitly provided.)  Thanks.

  14. Unknown User (lannoye.xavier@gmail.com)

    Hi

    we're trying to reset our user's password using the following groovy script. Even if the url works through our browser, the groovy code fails on a"not found" exception (even if the user exists!)

    import groovyx.net.http.RESTClient
    import org.apache.http.HttpRequestInterceptor
    import org.apache.http.HttpRequest
    import org.apache.http.protocol.HttpContext
    import groovyx.net.http.HTTPBuilder
    import java.lang.reflect.Method
    import static groovyx.net.http.Method.GET
    import static groovyx.net.http.ContentType.JSON
    
    
    def String authString = "dir:pwd".getBytes().encodeBase64().toString()
    def authSite = new RESTClient("http://blabla:1234/baseurl/crowd/rest/usermanagement/1/", JSON)
    authSite.headers = \['Authorization': "Basic ${authString}", 'Accept': "application/json", 'Content-Type': "application/json"\]
    def result = authSite.post(path: 'user/mail/password?username=toto')
    

    what did we miss?

    thanks for your help

    1. Unknown User (lannoye.xavier@gmail.com)

      A long search
      a pair programming
      a googling on http://groovy.329449.n5.nabble.com/RESTClient-and-JSON-td333800.html

      we finally raised up this solution (could be helpful for others)

      import groovyx.net.http.RESTClient
      import org.apache.http.HttpRequestInterceptor
      import org.apache.http.HttpRequest
      import org.apache.http.protocol.HttpContext
      import groovyx.net.http.HTTPBuilder
      import java.lang.reflect.Method
      import static groovyx.net.http.Method.GET
      import static groovyx.net.http.ContentType.JSON
      
      
      
      def String authString = "dir:pwd".getBytes().encodeBase64().toString()
      def authSite = new RESTClient("http://blabla:1234/baseurl/crowd/rest/usermanagement/1/")
      authSite.headers = ["Authorization": "Basic ${authString}"]
      
      def response = authSite.post(path: 'user/mail/password',
      query:[username: "toto"],
      contentType: JSON,
      requestContentType:&nbsp; JSON
      )
  15. Unknown User (avdd@careflight.org)

    IMPORTANT NOTE FOR API CONSUMERS

    The JSON format for the REST API is patently unsupported by Atlassian, according to the evidence on this page.

  16. Unknown User (thies@te-con.nl)

    Say I have this scenario:

    I defined two applications in crowd, "labs" and "portal". User "thies" has access to only "portal", not to "labs".

    When user "thies" logs in I authenticate the user by posting to the /session URI, doing basic authentication with the "portal" app. This goes well and gives me the principal token.

    Then I do a get on the /session uri and provide the principal token, doing basic authentication with the "labs" appname and password; I still get a valid response while I was expecting  - as the user doesn't have access to the "labs" app - to get an invalid response. Are my assumptions wrong? Is it possible - using the rest api - to check to which applications a user has access, with just the token? I noticed that in the soap call you have to provide the app token as well.

    1. Unknown User (thies@te-con.nl)

      To reply to myself; doing a get on session/

      Unknown macro: {token}

      will only retrieve the user for that token and does not do any authorization.

  17. Anonymous

    Hi

    I am authenticating with this json file:

    {"username":"bama1",
     "password":"Bama123",
     "validation-factors": {
            "validationFactors":[

    Unknown macro: {"name"}

    ]}
    }
    {"username":"myname",

     "password":"mypass",

     "validation-factors":

    Unknown macro: {         "validationFactors"}

    }

    just running curl:

    curl -X POST -T ssopost3.txt -u appdev:apppass -H "Accept: application/json" -H "Content-Type: application/json" "http://xx.xxx.xx.xx:17004/crowd/rest/usermanagement/1/session"

    I am successfully getting token key, 
    But when I am opening crowd console in the firefox browser, observing login page and adding cookie 'crowd.token_key'.

    And when I reloading the page - there is no signed user there. But if I am loggin from this console page and
    then trying to check session token from cookie - it is a valid token, I could get user info with curl requests on it,
    I even could logout this user with curl request and page will be non-logged.

    Kinda strange, could you help please ?

    1. Anonymous

      sorry for my English,  I meant that token from curl request does not recognized by web crowd console, it still show

      login new user page. 

      Could it be related to empty validationFactors ? I have used remote_address as localhost, external ip, ip of the crowd server (

      getting different tokens, by the way) but no one was right as a cookie for a web crowd console.

  18. Anonymous

    From docs above:

    Either user password needs to be valid or validate-password query param must be set to false

    This poses a problem – anyone with access to /session can generate a user token with or without knowledge of the user's password.
    How can this functionality be disabled?
    1. Operations cannot be individually disabled. All resources are protected with an authentication filter that requieres valid application credentials. If you have valid application credentials, you can change the user password or delete the user, therefore having the ability to generate a user token without knowledge of the user's password does not introduce any risk.

      1. Anonymous

        This is not correct.

        Both of these operations also require a separate permission level, please read Atlassian's documentation on this: https://confluence.atlassian.com/display/CROWD/Specifying+an+Application's+Directory+Permissions

         

        Changing the user's password or deleting the user is an intrusive operation that will leave the user's account broken; being able to generate a user token allows an application to silently impersonate a user to other applications without consent.

        1. You're right, you can implement defence in depth by restricting the application permissions, but it is not currently possible to distinguish between the different modes to create a session. Please feel free to open a feature request at jira.atlassian.com for that.

  19. How to integrate crowd and teamcity to realize SSO ?Who can give me some help? thanks.

  20. I'd like to see an example on how to send the sso session token cookie to crowd server using cURL in command line. I can get and save the cookie but when I try to use it the server just says 'Application failed to authenticate'.

    I have understood that after you get the cookie you don't need to authenticate with application name and password any more but you can use the cookie instead.

    I can use the REST API with name/password authentication but i'd prefer to use the sso session token cookie.

    I have saved the cookie with '-c cookie.txt' but using it with '-b cookie.txt" doesn't work. 

    curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X "POST" -d @auth.txt http://localhost:8095/crowd/rest/usermanagement/latest/authentication?username=testi -b keksi.txt -v
    * Hostname was NOT found in DNS cache
    * Trying 127.0.0.1...
    * Connected to localhost (127.0.0.1) port 8095 (#0)
    > POST /crowd/rest/usermanagement/latest/authentication?username=testi HTTP/1.1
    > User-Agent: curl/7.35.0
    > Host: localhost:8095
    > Cookie: JSESSIONID=A7F0E8979757270EAD05B3DDF86ED302
    > Accept: application/xml
    > Content-Type: application/xml
    > Content-Length: 81
    >
    * upload completely sent off: 81 out of 81 bytes
    < HTTP/1.1 401 Unauthorized
    * Server Apache-Coyote/1.1 is not blacklisted
    < Server: Apache-Coyote/1.1
    < X-Embedded-Crowd-Version: Crowd/2.7.1
    < X-Crowd-User-Management-Version: 1.4
    < WWW-Authenticate: BASIC realm="Crowd REST Service"
    < Content-Type: text/plain;charset=UTF-8
    < Transfer-Encoding: chunked
    < Date: Wed, 04 Feb 2015 12:39:00 GMT
    <
    * Connection #0 to host localhost left intact
    Application failed to authenticate

    If you wonder why I use version 2.7.1 it is because I had so much difficulties to implement my own custom directory connector with newer version than 2.7.1.  Version 2.7.1 works ok and I will try to make connector work with newer versions soon.

     

    1. If you want to use SSO, don't use the /authenticate resource.

      Instead, create a user session token by sending a POST to /session, and then validate it by sending a POST to /session/{token}. Both requests must be always authenticated with application credentials, but you only need to provide the user credentials when creating the token. Once the token is created, you don't need the user credentials anymore.

      The Crowd REST API does not use cookies for user authentication.

  21. Is is possible to fetch the last login timestamp of a user?

    1. Do a request to GET /user?username=USERNAME&expand=attributes. In directories that support it (Internal Directory), the user has attributes that indicate when the user logged in for the last time and, if using SSO, when the user validated the token for the last time:

      ...
          <attribute name="lastActive">
            <link href="http://localhost:4990/crowd/rest/usermanagement/1/user/attribute?username=admin&amp;attributename=lastActive" rel="self"/>
            <values>
              <value>1424124640888</value>
            </values>
          </attribute>
          <attribute name="lastAuthenticated">
            <link href="http://localhost:4990/crowd/rest/usermanagement/1/user/attribute?username=admin&amp;attributename=lastAuthenticated" rel="self"/>
            <values>
              <value>1424124609782</value>
            </values>
          </attribute>
      ...
  22. When creating new users via the REST API, which Crowd Directory will they be created in?  Is there a way to specify which directory the users are created in?

    1. Updates will be performed in the first writable directory in directory order for the application, see Specifying the Directory Order for an Applicationfor details.

  23. The below REST call is returning 200 (OK) when the group name not exists and the parent group exists, whereas the documentation says that this call should return 404:

    GET /group/parent-group/direct?groupname=GROUPNAME&parent-groupname=PARENT-GROUPNAME

    1. Could you please raise an CWD issue at https://jira.atlassian.com/ with a description of how to reproduce the problem? Thank you.

  24. Is there a way to create applications in crowd using the api?