#Stormpath is Joining Okta We are incredibly excited to announce that Stormpath is joining forces with Okta. Please visit the Migration FAQs for a detailed look at what this means for Stormpath users.
We're available to answer all questions at support@stormpath.com.
Stormpath Ruby SDK
Stormpath is the first easy, secure user management and authentication service for developers. This is the Ruby SDK to ease integration of its features with any Ruby language based application.
Install
$ gem install stormpath-sdk
Provision Your Stormpath Account
If you have not already done so, register as a developer on Stormpath and set up your API credentials and resources:
-
Create a Stormpath developer account and create your API Keys downloading the
apiKey.properties
file into a.stormpath
folder under your local home directory. -
Through the Stormpath Admin UI, create yourself an Application Resource. On the Create New Application screen, make sure the "Create a new directory with this application" box is checked. This will provision a Directory Resource along with your new Application Resource and link the Directory to the Application as a Login Source. This will allow users associated with that Directory Resource to authenticate and have access to that Application Resource.
It is important to note that although your developer account comes with a built-in Application Resource (called "Stormpath") - you will still need to provision a separate Application Resource.
-
Take note of the REST URL of the Application you just created. Your web application will communicate with the Stormpath API in the context of this one Application Resource (operations such as: user-creation, authentication, etc.)
Getting Started
-
Require the Stormpath Ruby SDK
require 'stormpath-sdk'
-
Create a client using the API key properties file
client = Stormpath::Client.new api_key_file_location: File.join(ENV['HOME'], '.stormpath', 'apiKey.properties')
-
List all your applications and directories
client.applications.each do |application| p "Application: #{application.name}" end client.directories.each do |directory| p "Directory: #{directory.name}" end
-
Get access to the specific application and directory using the URLs you acquired above.
application = client.applications.get(application_url) directory = client.directories.get(directory_url)
-
Create an account for a user on the directory.
account = directory.accounts.create( given_name: 'John', surname: 'Smith', email: 'john.smith@example.com', username: 'johnsmith', password: '4P@$$w0rd!' )
-
Update an account
account.given_name = 'Johnathan' account.middle_name = 'A.' account.save
-
Authenticate the Account for use with an application:
auth_request = Stormpath::Authentication::UsernamePasswordRequest.new 'johnsmith', '4P@$$w0rd!' begin auth_result = application.authenticate_account auth_request account = auth_result.account rescue Stormpath::Error => e #If credentials are invalid or account doesn't exist end
-
Send a password reset request
application.send_password_reset_email 'john.smith@example.com'
-
Create a group in a directory
directory.groups.create(name: 'Admins')
-
Add the account to the group
group.add_account account
-
Check for account inclusion in group by reloading the account
account = client.accounts.get(account.href) is_admin = account.groups.any? { |group| group.name == 'Admins' }
Common Uses
Creating a client
All Stormpath features are accessed through a
Stormpath::Client
instance, or a resource
created from one. A client needs an API key (made up of an id and a
secret) from your Stormpath developer account to manage resources
on that account. That API key can be specified any number of ways
in the hash of values passed on Client initialization:
-
The location of API key properties file:
client = Stormpath::Client.new api_key_file_location: '/some/path/to/apiKey.properties'
You can even identify the names of the properties to use as the API key id and secret. For example, suppose your properties was:
foo=APIKEYID bar=APIKEYSECRET
You could load it with the following:
client = Stormpath::Client.new api_key_file_location: '/some/path/to/apiKey.properties', api_key_id_property_name: 'foo', api_key_secret_property_name: 'bar'
-
Passing in a Stormpath::APIKey instance:
api_key = Stormpath::ApiKey.new api_id, api_secret client = Stormpath::Client.new api_key: api_key
-
By explicitly setting the API key id and secret:
client = Stormpath::Client.new api_key: { id: api_id, secret: api_secret }
-
By passing a composite application url to
Application.load
:composite_url = "http://#{api_key_id}:#{api_key_secret}@api.stormpath.com/v1/applications/#{application_id}" application = Stormpath::Resource::Application.load composite_url client = application.client
To change the base_url for the Enterprise product, pass the following option to Stormpath::Client.new()
:
client = Stormpath::Client.new(
api_key_file_location: '/some/path/to/apiKey.properties',
base_url: 'https://enterprise.stormpath.io/v1'
)
-
By passing a composite application url to
Application.load
:composite_url = "http://#{api_key_id}:#{api_key_secret}@api.stormpath.com/v1/applications/#{application_id}" application = Stormpath::Resource::Application.load composite_url client = application.client
Accessing Resources
Most of the work you do with Stormpath is done through the applications and directories you have registered. You use the client to access them with their REST URL:
application = client.applications.get(application_url)
directory = client.directories.get(directory_url)
The applications
and directories
property on a
client instance are also Enumerable
allowing you to iterate
and scan for resources via that interface.
Additional resources are accounts
, groups
,
group_membership
, and the single reference to your
tenant
.
Creating Resources
Applications and directories can be created directly off the client.
application = client.applications.create(name: 'foo', description: 'bar')
directory = client.directories.create(name: 'foo', description: 'bar')
Collections
Search
Resource collections can be searched by a general query string or by attribute.
Passing a string to the search method will filter by any attribute on the collection:
client.applications.search 'foo'
To search a specific attribute or attributes, pass a hash:
client.applications.search name: 'foo', description: 'bar'
Pagination
Collections can be paginated using chainable Arel-like methods. offset
is the zero-based starting index in the entire collection of the first item to return. Default is 0. limit
is the maximum number of collection items to return for a single request. Minimum value is 1. Maximum value is 100. Default is 25.
client.applications.offset(10).limit(100).each do |application|
# do something
end
Order
Collections can be ordered. In the following example, a paginated collection is ordered.
client.applications.offset(10).limit(100).order('name asc,description desc')
Entity Expansion
A resource's children can be eager loaded by passing the entity expansion object as the second argument to a call to get
.
expansion = Stormpath::Resource::Expansion.new 'groups', 'group_memberships'
client.accounts.get(account.href, expansion)
limit
and offset
can be specified for each child resource by calling add_property
.
expansion = Stormpath::Resource::Expansion.new
expansion.add_property 'groups', offset: 5, limit: 10
client.accounts.get(account.href, expansion)
ID Site
ID Site is a set of hosted and pre-built user interface screens that easily add authentication to your application. ID Site can be accessed via your own custom domain like id.mydomain.com and shared across multiple applications to create centralized authentication if needed. To use ID Site an url needs to be generated which contains JWT token as a parameter.
ID Site Login
In order to use ID Site an url needs to be generated. You also need to redirect to the generated url. You can call create_id_site_url which is on application object. For example if you are using sinatra the code would look something like this:
get ‘login’ do
redirect application.create_id_site_url callback_uri: “#{callback_uri}”
end
The application will be an instance of your application. callback_uri is a url with which you want to handle the ID Site information, this url also needs to be set in the Stormpath’s dashboard on ID Site settings page as Authorized Redirect URLs.
Using ID Site for multitenancy
When a user wants to login to your application, you may want to specify an organization for the user to login to. Stormpath ID Site is configurable to support multitenancy with Organization resources
application.create_id_site_url({
callback_uri: 'https://trooperapp.com/callback',
organization_name_key: 'stormtrooper',
show_organization_field: true
});
Using Subdomains
In some cases, you may want to show the organization that the user is logging into as a subdomain instead of an form field. To configure this, you need to use a wildcard certificate when setting up your custom domain with ID Site. Otherwise, the Stormpath infrastructure will cause browser SSL errors.
Once a wildcard certificate is configured on your domain, you can tell ID Site to use a subdomain to represent the organization:
application.create_id_site_url({
callback_uri: 'https://trooperapp.com/callback',
organization_name_key: 'stormtrooper',
use_subdomain: true
});
Specifying the Organization
In the case where you are using a subdomain to designate the organization, you can tell ID Site which organization the user is logging into to.
application.create_id_site_url({
callback_uri: 'https://trooperapp.com/callback',
organization_name_key: 'stormtrooper',
show_organization_field: true
})
Handle ID Site Callback
For any request you make for ID Site, you need to specify a callback uri. To parse the information from the servers response and to decode the data from the JWT token you need to call the handle_id_site_callback method and pass the Request URI.
For example in your sinatra app this would look something like this:
app.get ‘/callback' do
user_data = application.handle_id_site_callback(request.url)
end
NOTE: A JWT Response Token can only be used once. This is to prevent replay attacks. It will also only be valid for a total of 60 seconds. After which time, You will need to restart the workflow you were in.
Other ID Site Options
There are a few other methods that you will need to concern yourself with when using ID Site. Logging out a User, Registering a User, and a User who has forgotten their password. These methods will use the same information from the login method but a few more items will need to be passed into the array. For example if you have a sinatra application.
Logging Out a User
app.get ‘/logout' do
user_data = application.handle_id_site_callback(request.url)
redirect application.create_id_site_url callback_uri: “#{callback_uri}”, logout: true
end
Registering a User
app.get ‘/register' do
user_data = application.handle_id_site_callback(request.url)
redirect application.create_id_site_url callback_uri: “#{callback_uri}”, path: ‘/#/register'
end
Forgot Link
app.get ‘/forgot' do
user_data = application.handle_id_site_callback(request.url)
redirect application.create_id_site_url callback_uri: “#{callback_uri}”, path: ‘/#/forgot'
end
Again, with all these methods, You will want your application to link to an internal page where the JWT is created at that time. Without doing this, a user will only have 60 seconds to click on the link before the JWT expires.
NOTE: A JWT will expire after 60 seconds of creation.
Fetch Stormpath Access Token with username and password
Stormpath can generate a brand new Access Token using the password grant type: User's credentials.
To fetch the oauth token use the following snippet
grant_request = Stormpath::Oauth::PasswordGrantRequest.new(email, password)
response = application.authenticate_oauth(grant_request)
Just like with logging-in a user, it is possible to generate a token against a particular Application’s Account Store or Organization. To do so, specify the Account Store’s href or Organization’s nameKey as a parameter in the request:
grant_request = Stormpath::Oauth::PasswordGrantRequest.new(email, password, organization_name_key: 'my-stormpath-organization')
response = application.authenticate_oauth(grant_request)
Exchange ID Site token for a Stormpath Access Token
After the user has been authenticated via ID Site, a developer may want to control their authorization with an OAuth 2.0 Token. This is done by passing the JWT similar to the way we passed the user’s credentials as described in Generating an OAuth 2.0 Access Token. The difference is that instead of using the password grant type and passing credentials, we will use the id_site_token type and pass the JWT we got from the ID Site more info here.
To exchange ID Site token for the oauth token use the following snippet
grant_request = Stormpath::Oauth::IdSiteGrantRequest.new jwt_token
response = application.authenticate_oauth grant_request
Exchange Client Credentials for a Stormpath Access Token
As a developer, I want to authenticate API Keys directly against my application endpoint, so that I can have Stormpath generate an application token that I can use for a session.
Create an API Key for an account:
account_api_key = account.api_keys.create({})
Then create an client credentials request and get a authentication result:
client_credentials_grant_request = Stormpath::Oauth::ClientCredentialsGrantRequest.new(
account_api_key.id,
account_api_key.secret
)
authentication_result = application.authenticate_oauth(client_credentials_grant_request)
puts authentication_result.access_token
puts authentication_result.refresh_token
Exchange ID site token for a Stormpath Access Token
As a developer, I want to authenticate the user on ID Site but get an access token that I can store on the client to use to access my API. The oauth token endpoint will validate that:
- the JWT is not tampered
- has not expired
- the account is still associated with the application and will return an access token
- the status claim is either AUTHENTICATED or REGISTERED
If you want to create a stormpath grant request with status authenticated
you need to pass the account, application and api key id:
stormpath_grant_request = Stormpath::Oauth::StormpathGrantRequest.new(
account,
application,
api_key_id
)
If you have the status attribute set to registered
then create the request like so:
stormpath_grant_request = Stormpath::Oauth::StormpathGrantRequest.new(
account,
application,
api_key_id,
:registered
)
And lastly authenticate with the created request instance:
authentication_result = application.authenticate_oauth(stormpath_grant_request)
puts authentication_result.access_token
puts authentication_result.refresh_token
Registering Accounts
Accounts are created on a directory instance. They can be created in two ways:
-
With the
create_account
method:account = directory.create_account({ given_name: 'John', surname: 'Smith', email: 'john.smith@example.com', username: 'johnsmith', password: '4P@$$w0rd!' })
This metod can take an additional flag to indicate if the account can skip any registration workflow configured on the directory.
## Will skip workflow, if any account = directory.create_account account_props, false
-
Creating it directly on the
accounts
collection property on the directory:account = directory.accounts.create( given_name: 'John', surname: 'Smith', email: 'john.smith@example.com', username: 'johnsmith', password: '4P@$$w0rd!' )
Both these methods can take either a Hash
of the account
properties, or a Stormpath::Account
.
If the directory has been configured with an email verification workflow
and a non-Stormpath URL, you have to pass the verification token sent to
the URL in a sptoken
query parameter back to Stormpath to
complete the workflow. This is done through the
verify_email_token
on the accounts
collection.
For example, suppose you have a Sinatra application
that is handling the email verification at the path
/users/verify
. You could use the following code:
get '/users/verify' do
token = params[:sptoken]
account = client.accounts.verify_email_token token
#proceed to update session, display account, etc
end
Create an Account with an Existing Password Hash
If you are moving from an existing user repository to Stormpath, you may have existing password hashes that you want to reuse to provide a seamless upgrade path for your end users. More info about this feature can be found here
Example of creating an account with existing SHA-512 password hash. For details on other hashing algorithms check the documentation
directory.accounts.create({
username: "jlucpicard",
email: "captain@enterprise.com",
given_name: "Jean-Luc",
surname: "Picard",
password: "$stormpath2$SHA-512$1$ZFhBRmpFSnEwVEx2ekhKS0JTMDJBNTNmcg==$Q+sGFg9e+pe9QsUdfnbJUMDtrQNf27ezTnnGllBVkQpMRc9bqH6WkyE3y0svD/7cBk8uJW9Wb3dolWwDtDLFjg=="
}, password_format: 'mcf')
Authentication
Authentication is accomplished by passing a username or an email and a
password to authenticate_account
of an application we've
registered on Stormpath. This will either return a
Stormpath::Authentication::AuthenticationResult
instance if
the credentials are valid, or raise a Stormpath::Error
otherwise. In the former case, you can get the account
associated with the credentials.
auth_request =
Stormpath::Authentication::UsernamePasswordRequest.new 'johnsmith', '4P@$$w0rd!'
begin
auth_result = application.authenticate_account auth_request
account = auth_result.account
rescue Stormpath::Error => e
#If credentials are invalid or account doesn't exist
end
The UsernamePasswordRequest
can take an optional link to the application’s accountStore (directory or group) or the Organization nameKey. Specifying this attribute can speed up logins if you know exactly which of the application’s assigned account stores contains the account: Stormpath will not have to iterate over the assigned account stores to find the account to authenticate it. This can speed up logins significantly if you have many account stores (> 15) assigned to the application.
The UsernamePasswordRequest
can receive the AccountStore in three ways.
Passing the organization, directory or group instance:
auth_request =
Stormpath::Authentication::UsernamePasswordRequest.new 'johnsmith', '4P@$$w0rd!', account_store: organization
Passing the organization, directory or group href:
auth_request =
Stormpath::Authentication::UsernamePasswordRequest.new 'johnsmith', '4P@$$w0rd!', account_store: { href: organization.href }
Passing the organization name_key:
auth_request =
Stormpath::Authentication::UsernamePasswordRequest.new 'johnsmith', '4P@$$w0rd!', account_store: { name_key: organization.name_key }
Authentication Against a SAML Directory
SAML is an XML-based standard for exchanging authentication and authorization data between security domains. Stormpath enables you to allow customers to log-in by authenticating with an external SAML Identity Provider.
Stormpath as a Service Provider
The specific use case that Stormpath supports is user-initiated single sign-on. In this scenario, a user requests a protected resource (e.g. your application). Your application, with the help of Stormpath, then confirms the users identity in order to determine whether they are able to access the resource. In SAML terminology, the user is the User Agent, your application (along with Stormpath) is the Service Provider, and the third-party SAML authentication site is the Identity Provider or IdP.
The broad strokes of the process are as follows:
- User Agent requests access from Service Provider
- Service Provider responds with redirect to Identity Provider
- Identity Provider authenticates the user
- Identity provider redirects user back to Service Provider along with SAML assertions.
- Service Provider receives SAML assertions and either creates or retrieves Account information
Configuring Stormpath as a Service Provider
Configuration is stored in the Directory's Provider resource. Here we will explain to you the steps that are required to configure Stormpath as a SAML Service Provider.
Step 1: Gather IDP Data
You will need the following information from your IdP:
- SSO Login URL - The URL at the IdP to which SAML authentication requests should be sent. This is often called an "SSO URL", "Login URL" or "Sign-in URL".
- SSO Logout URL - The URL at the IdP to which SAML logout requests should be sent. This is often called a "Logout URL", "Global Logout URL" or "Single Logout URL".
- Signing Cert - The IdP will digitally sign auth assertions and Stormpath will need to validate the signature. This will usually be in .pem or .crt format, but Stormpath requires the text value.
- Signing Algorithm - You will need the name of the signing algorithm that your IdP uses. It will be either "RSA-SHA256" or "RSA-SHA1".
Step 2: Configure Your SAML Directory
Input the data you gathered in Step 1 above into your Directory's Provider resource, and then pass that along as part of the Directory creation HTTP POST:
provider = "saml"
request = Stormpath::Provider::AccountRequest.new(provider, :access_token, access_token)
application.get_provider_account(request)
client.directories.create(
name: "infinum_directory",
description: "random description",
provider: {
provider_id: "saml"
}
)
to get the data about the provider just type
directory.provider
provider method returns instance of SamlProvider and you can access the following data
dir_provider = directory.provider
dir_provider.provider_id
dir_provider.sso_login_url
dir_provider.sso_logout_url
dir_provider.encoded_x509_signing_cert
dir_provider.request_signature_algorithm
dir_provider.service_provider_metadata
dir_provider.attribute_statement_mapping_rules
dir_provider.created_at
dir_provider.modified_at
Retrieve Your Service Provider Metadata
Next you will have to configure your Stormpath-powered application as a Service Provider in your Identity Provider. This means that you will need to retrieve the correct metadata from Stormpath.
In order to retrieve the required values, start by sending a GET to the Directory's Provider:
directory.service_provider_metadata
service_provider_metadata method returns instance of SamlServiceProviderMetadata and you can access the following values
dir_provider_metadata = directory.service_provider_metadata
dir_provider_metadata.href
dir_provider_metadata.entity_id
dir_provider_metadata.x509_signing_cert
dir_provider_metadata.assertion_consumer_service_post_endpoint
dir_provider_metadata.created_at
dir_provider_metadata.modified_at
From this metadata, you will need two values:
- Assertion Consumer Service URL: This is the location the IdP will send its response to.
- X509 Signing Certificate: The certificate that is used to sign the requests sent to the IdP. If you retrieve XML, the certificate will be embedded. If you retrieve JSON, you'll have to follow a further /x509certificates link to retrieve it.
You will also need two other values, which will always be the same:
- SAML Request Binding: Set to HTTP-Redirect.
- SAML Response Binding: Set to HTTP-Post.
Step 4: Configure Your Service Provider in Your Identity Provider
Log-in to your Identity Provider (Salesforce, OneLogin, etc) and enter the information you retrieved in the previous step into the relevant application configuration fields. The specific steps to follow here will depend entirely on what Identity Provider you use, and for more information you should consult your Identity Provider's SAML documentation.
Step 5: Configure Your Application
The Stormpath Application
Resource has two parts that are relevant to SAML:
- an
authorizedCallbackUri
Array that defines the authorized URIs that the IdP can return your user to. These should be URIs that you host yourself. - an embedded
samlPolicy
object that contains information about the SAML flow configuration and endpoints.
application.authorized_callback_uris = ["https://myapplication.com/whatever/callback", "https://myapplication.com/whatever/callback2"]
application.save
Step 6: Add the SAML Directory as an Account Store
The next step is to map the new Directory to your Application with an Account Store Mapping.
Step 7: Configure SAML Assertion Mapping
The Identity Provider's SAML response contains assertions about the user's identity, which Stormpath can use to create and populate a new Account resource.
<saml:AttributeStatement>
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">jane@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="location" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">Tampa, FL</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
The Attribute Assertions (<saml:AttributeStatement>
) are brought into Stormpath and become Account and customData attributes.
SAML Assertion mapping is defined in an attributeStatementMappingRules object found inside the Directory's Provider object, or directly: /v1/attributeStatementMappingRules/$RULES_ID
.
Mapping Rules
The rules have three different components:
- name: The SAML Attribute name
- name_format: The name format for this SAML Attribute, expressed as a Uniform Resource Name (URN).
-
account_attributes: This is an array of Stormpath Account or customData (
customData.$KEY_NAME
) attributes that will map to this SAML Attribute.
In order to create the mapping rules, we simply send the following:
rule = {
name: 'uid',
account_attributes: ['username']
}
dir.attribute_statement_mapping_rules.items = [rule]
dir.attribute_statement_mapping_rules.save
Password Reset
A password reset workflow, if configured on the directory the account is
registered on, can be kicked off with the
send_password_reset_email
method on an application:
application.send_password_reset_email 'john.smith@example.com'
If the workflow has been configured to verify through a non-Stormpath
URL, you can verify the token sent in the query parameter
sptoken
with the verify_password_reset_token
method on the application.
For example, suppose you have a Sinatra application that is verifying the tokens. You use the following to carry it out:
get '/users/verify' do
token = params[:sptoken]
account = application.verify_password_reset_token token
#proceed to update session, display account, etc
end
With the account acquired you can then update the password:
account.password = new_password
account.save
NOTE : Confirming a new password is left up to the web application code calling the Stormpath SDK. The SDK does not require confirmation.
Social Providers
To access or create an account in an already created social Directory (facebook, google, github, linkedin), it is required to gather Authorization Code on behalf of the user. This requires leveraging Oauth 2.0 protocol and the user's consent for your applications permissions. Once you have the access_token you can access the account via get_provider_account method.
provider = ‘facebook’ # can also be google, github, linkedin
request = Stormpath::Provider::AccountRequest.new(provider, :access_token, access_token)
application.get_provider_account(request)
ACL through Groups
Memberships of accounts in certain groups can be used as an
authorization mechanism. As the groups
collection property
on an account instance is Enumerable
, you can use any of
that module's methods to determine if an account belongs to a specific
group:
account.groups.any? {|group| group.name == 'administrators'}
You can create groups and assign them to accounts using the Stormpath web console, or programmatically. Groups are created on directories:
group = directory.groups.create(name: 'administrators')
Group membership can be created by:
-
Explicitly creating a group membership resource with your client:
group_membership = client.group_memberships.create(group: group, account: account)
-
Using the
add_group
method on the account instance:account.add_group group
-
Using the
add_account
method on the group instance:group.add_account account
You will need to reload the account or group resource after these operations to ensure they've picked up the changes.
Working with Organizations
An Organization
is a top-level container for Account Stores. You can think of an Organization as a tenant for your multi-tenant application. This is different than your Stormpath Tenant, which represents your tenant in the Stormpath system. Organizations are powerful because you can group together account stores that represent a tenant.
-
Locate an organization
client.organizations.search(name: 'Finance Organization')
-
Create an organization
client.organizations.create(name: 'Finance Organization', name_key: 'finance-organization')
-
Adding an account store to an organization
client.organization_account_store_mappings.create( account_store: { href: directory_or_group.href }, organization: { href: organization.href } )
-
Adding an Organization to an Application as an Account Store
client.account_store_mappings.create(application: application, account_store: organization)
Add Custom Data to Accounts or Groups
Account and Group resources have predefined fields that are useful to many applications, but you are likely to have your own custom data that you need to associate with an account or group as well.
For this reason, both the account and group resources support a linked custom_data resource that you can use for your own needs.
Set Custom Data
account = Stormpath::Resource::Account.new({ email: "test@example.com", given_name: 'Ruby SDK', password: 'P@$$w0rd', surname: 'SDK',})
account.custom_data["rank"] = "Captain"
account.custom_data["birth_date"] = "2305-07-13"
account.custom_data["birth_place"] = "La Barre, France"
directory.create_account account
Notice how we did not call account.custom_data.save - creating the account (or updating it later via save) will automatically persist the account's customData resource. The account 'knows' that the custom data resource has been changed and it will propogate those changes automatically when you persist the account.
Groups work the same way - you can save a group and it's custom data resource will be saved as well.
Delete a specific Custom Data field
account.custom_data["birth_date"] #=> "2305-07-13"
account.custom_data.delete("birth_date")
account.custom_data.save
Delete all Custom Data
account.custom_data.delete
Testing
Setup
The functional tests of the SDK run against a Stormpath tenant. In that account they automatically create and destroy resources.
The following environment variables need to be set:
-
STORMPATH_CLIENT_APIKEY_ID
- Theid
from your Stormpath API key. -
STORMPATH_CLIENT_APIKEY_SECRET
- Thesecret
from your Stormpath API key.
Running
Once properly configured, start the redis server with redis-server
and the tests can be run as the default
Rake
task:
$ rake
Or by specifying the spec
task:
$ rake spec
Or through rspec
Contributing
You can make your own contributions by forking the development
branch, making your changes, and issuing pull-requests on the
development
branch.
Building the Gem
To build and install the development branch yourself from the latest source:
$ git clone git@github.com:stormpath/stormpath-sdk-ruby.git
$ cd stormpath-sdk-ruby
$ rake gem
$ gem install pkg/stormpath-sdk-{version}.gem
Releasing the Gem
- Update the gem version following semantic versioning
- Update the version date
- Update the CHANGES.md
- Run
rake release
Quick Class Diagram
+-------------+
| Application |
| |
+-------------+
+ 1
|
| +-------------+
| | LoginSource |
o- - - - - -| |
| +-------------+
|
v 0..*
+--------------+ +--------------+
| Directory | 1 1 | Account |1
| |<----------+| |+----------+
| | | | |
| | 1 0..* | |0..* |
| |+---------->| |+-----+ |
| | +--------------+ | | +-----------------+
| | | | | GroupMembership |
| | o- - o - - - - | |
| | +--------------+ | | +-----------------+
| | 1 0..* | Group |1 | |
| |+---------->| |<-----+ |
| | | | |
| | 1 1 | |0..* |
| |<----------+| |<----------+
+--------------+ +--------------+
Copyright & Licensing
Copyright © 2013 Stormpath, Inc. and contributors.
This project is licensed under the Apache 2.0 Open Source License.
For additional information, please see the full Project Documentation.