10_public:3rd_party_app_development

Diese Version wurde durch eine neuere bestätigte Version ersetzt.DiffDiese Version (2017/10/27 13:22) ist ein Entwurf.
Überprüfungen: 0/1

Dies ist eine alte Version des Dokuments!


startSectionEdit: $data "plugin_wrap_start" is NOT an array! One of your plugins needs an update.
startSectionEdit: $data "plugin_wrap_end" is NOT an array! One of your plugins needs an update.
startSectionEdit: $data "plugin_wrap_start" is NOT an array! One of your plugins needs an update.
startSectionEdit: $data "plugin_wrap_end" is NOT an array! One of your plugins needs an update.
startSectionEdit: $data "plugin_wrap_start" is NOT an array! One of your plugins needs an update.
startSectionEdit: $data "plugin_wrap_end" is NOT an array! One of your plugins needs an update.
startSectionEdit: $data "plugin_wrap_start" is NOT an array! One of your plugins needs an update.
startSectionEdit: $data "plugin_wrap_end" is NOT an array! One of your plugins needs an update.

App/Service Development

1)

You have a new service (Webapplication, mobile app, desktop application, …) and you would like using either our AAI (Authentication and Authorization Infrastructure) or access to one of our APIs (Application Progammable Interface) or both. We provide both - a SAML2 infrastructure (Shibboleth) and an OpenID Connect infrastructure.

First thing you need to decide is wether your service should be a Shibboleth service provider or a service using OpenID Connect. If you just want authentication and authorization including attribute releasing in a browser-only environement your probably want SAML2 (Shibboleth), however OpenID Connect is the more modern protocol and you can achieve the same. In the end it is up to you what you would like to implement. As soon as you want more besides just authenticate in a browser-only environement, you will need OpenID Connect since it is the only way to interact with our API services (resource server).

It has to be mentioned that our OpenID Connect IdP is a layer on the top of shibboleth, meaning every OpenID Connect provider is a shibboleth provider as well. But a shibboleth provider is not necessarily an OpenID Connect provider.

First thing you're required to do is regsiter your app.

There is no interface yet for self register your app.

Please write a mail to support@gselroth.com with the following information:

  1. App name
  2. App description
  3. App logo (OPTIONAL)
  4. Protocol (Shibboleth or OpenID Connect) (Usually you want OpenID Connect here)

If you have choosen Shibboleth for nr. 4, wee need the following additional information:

  1. URL to your SP (service provider) Metadata

If you have choosen OpenID Connect for nr. 4, wee need the following additional information:

  1. Client authentication method (Usually you want „client_secret_post“ here) (See OpenID-Connect Specification part 9)
  2. App type (Android app, JavaScript app, desktop app, webserver app, …)
  3. redirect_uri

Following API resource server are available:

NameAPI VersionURLTyp
IN2v1https://api.tam.chJSON/XML REST
CloudFSv1https://cloudfs.tam.ch/apiJSON/XML REST

Please continue to OpenId Connect if you work with the OpenID Connect protocol.

Our IdP is called https://aai.tam.ch, therefore you can receive the metadata from our IdP (identity provider) via:

https://aai.tam.ch/idp/shibboleth

As mentioned above we need your SP metadata to successfully connect your SP to our IdP.

It is possible to release the following attributes, be aware that all attributes with policy „all“ will get released to any shibboleth SP by default. If you require attributes from the policy „strict“ you will need special permission.

OID Attribute SourceDescription Policy
-dnLDAP:entryDNLDAP DNstrict
2.16.840.1.113730.3.1.3employeeNumberLDAP:employeeNumberuser id (only unique in each organization)all
2.5.4.42givenNameLDAP:givenName all
0.9.2342.19200300.100.1.3mailLDAP:mail all
-memberOfLDAP:memberOfgroup membershipstrict
0.9.2342.19200300.100.1.41mobileLDAP:mobile strict
2.5.4.10oLDAP:oSchuleall
2.5.4.11ouLDAP:ouorganization unitall
2.5.4.3snLDAP:snsurnameall
1.3.6.1.4.1.39555.19tamBirthdayLDAP:tamBirthday strict
1.3.6.1.4.1.39555.17tamClassLevelLDAP:tamClassLevel
1.3.6.1.4.1.39555.20tamGenderLDAP:tamGenderm, f, m/fall
1.3.6.1.4.1.39555.16tamPrimaryRoleLDAP:tamPrimaryRoleprimary group of membershipall
1.3.6.1.4.1.39555.3tamUniqueNameLDAP:tamUniqueNameunique username over all organizations [uid].[o]all
1.3.6.1.4.1.39555.23tamUUIDLDAP:tamUUIDtruly unique user identifierall
0.9.2342.19200300.100.1.1uidLDAP:uidusername (only unique in each organization )all
-tamClassCommonNameScripted Attributearray of classall

See the Shibboleth part if you have a shibboleth-only SP.

OpenID Connect is a modern protocol based on OAUTH2 meant for authentication. Read http://openid.net/connect if you are not familiar with the protocol.

Our provider is called https://accounts.tam.ch, therefore you can browse the discovery sheet viahttps://accounts.tam.ch/.well-known/openid-configuration

Your can receive the follwing user attributes by query the userinfo endpoint (See discovery) https://accounts.tam.ch/userinfo (Depending which scopes you have requested during requesting the token).

Attribute Description Scope
dnLDAP DNintranet
employee_numberuser id (only unique in each organization)intranet
given_namegiven nameprofile
namegiven name / family nameprofile
emailemail addressemail
member_ofgroup membershipsintranet
phone_numbermobile phone numberphone
organizationschoolintranet
organization_unitorganization unitintranet
family_namesurnameprofile
birthdaybirthdateprofile
tam_class_levelclass levelintranet
genderm, f, m/fprofile
tam_primary_roleprimary group of membershipintranet
preferred_usernameunique username over all organizations [uid].[o]profile
tam_uuidtruly unique user identifierintranet
uidusername (only unique in each organization )intranet

Use the authorization code flow for applications in which you can store the client_secret secretly.

The authorization code flow consists roughly of the following steps:

  1. Send authentication request to the authentication endpoint
  2. Let end-user authenticate at the authorization server
  3. Receive authorization code
  4. Send token request to the token endpoint using the authorization code
  5. Receive id token and access token

Authentication Request

To send an authentication request to the authentication endpoint (See discovery) https://accounts.tam.ch/auth you need to submit the following query parameters:

Parameter Values Description
response_typecodeThe response type, for auth code flow you need the value „code“
client_idclient_idYour client_id which you have received during registering your app
redirect_uriURIThe redirect_uri which you submitted during registering your app
scopeopenid profile email intranet offline_accessScopes to query, you should always request openid and profile. Note: If you want to query an intranet2 API you are required to request the scope intranet as well.
stateRandom StringRandom string to prevent cross-site-request-forgery attacks.

Example authentication request:

https://accounts.tam.ch/auth?redirect_uri=https%3A%2F%2Fcloudfs.tam.ch&scope=openid%20offline_access&client_id=my_client_id&response_type=code

If all parameters were valid, you receive an authentication response containing a code parameter. Its value is the authorization code.

Example authentication response:

https://cloudfs.tam.ch?state=3189f4685e2da677f86210b0f8f32451b5ac8c97de7097216542dde6d122e4fb.e44cf97d799330c8497996ead02edece&code=sJi902gBBCGG_icj0pOnFoQDL_o0Pju9RNXEjGGL9-Y

Access Token Request

To receive an access token you need to send a HTTP POST token request with the authorization code from the authentication response to the token endpoint (See discovery) https://accounts.tam.ch/token. You need to submit the following POST parameters:

Parameter Values Description
grant_typeauthorization_codeFor the authorization code flow the value „authorization_code“ is needed here
redirect_uri The redirect_uri of your app
code authorization code received in the authentication response
client_id The client_id you have received during registering your app (If you registered your app for the client_secret_post authentication method)
client_secret The client_secret you have received during registering your app (If you registered your app for the client_secret_post authentication method)

Additionally you have to authenticate the token request using the client authentication method you submitted during the registration of your app.

Example token request:

https://accounts.tam.ch/token with POST parameters grant_type=authorization_code&code=sJi902gBBcGG_icj0pOnFoQDL_o0Pju9RNXEjGGL9-Y&redirect_uri=https%3A%2F%2Fcloudfs.tam.ch&client_id=my_client_id&client_secret=my_client_secret

If you have choosen client_secret_basic as client authentication method during app registration your are required to send the client credentials in the basic scheme along the token POST request instead attaching them as POST parameters:

Authorization: Basic base64(my_client_id:my_client_secret)

The response from the authentication server contains a JSON document containing the access_token, the token_type, the refresh_token (If you requested the scope offline_access), the time until the token expires (expires_in) and the id token (JWT).

Example token response (JSON Body):

  {
   "access_token": "MsPh6Igqrfw98XYMqaAfbhTB2s79_iyovt7aBiF0bvo",
   "token_type": "Bearer",
   "refresh_token": "d1KQFvE-29SO-Es8lPbYhBCXDT2dpWANaKZmE3lBI9A",
   "expires_in": 3600,
   "id_token": "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOlwvXC9hY2NvdW50c2Rldi50YW0uY2hcL29wLmp3ayIsImtpZCI6ImFjY291bnRzZGV2LnRhbS5jaF8wMFMifQ.eyJpc3MiOiJodHRwczpcL1wvYWNjb3VudHNkZXYudGFtLmNoIiwic3ViIjoiMzAzMTMwMzEzMDMxMzAzMTMwMzEzMDMxMzAzMTMwMzExZThjOTkwZGRjY2VlZjBlMGVjOWUzN2Q1M2FiMThlYzgxYTIzN2Y3ZGM2YjRlOTgxYWQ2MDA0MzljMjcxMmI3IiwiYXVkIjpbImxvY2FsLXRlc3QtYXBwIl0sImV4cCI6MTUwNDE4MzA0NSwiaWF0IjoxNTA0MTgyNzQ1LCJhdF9oYXNoIjoicktCQWM0S0hlU3B4ekdEY2xRMGlfQSJ9.u4NUGCZ0uRoIXWeOQiQJ9EXgXC7qL205wUXeS-Vk5nXBhS62xoZ-pFH_-PUGhz5zbDTQpw49QqzgLmlOXSZocFdfNi1xsPlbDmTX0CPhMSZKGJ3jXKV0ciJL7joLwwK7Y3vZLsOuVLLzkFA9zEKsFN1bBrsWWcKisvLtd96CBGk6ClRZ8RhmVHWVTOJsaIAKxL4uH4LDtx9046s-9DVYpiJJsRd36YjbNCMGPi8ddY3OP-3Mhw0XErzlN8BuxcmzzWpt01kke9eqI2Gd_aA-JDP671nw6DQwiuQkPwTnvZheTOTZehg1BplWTbE3lGXyOjPix2xAMB-viffCFRsSaQ"
  }

With the access_token you have received above you can now query an API (resource server).

Refresh Access Token

With the refresh_token you have received you can get a new access_token.

You only get a refresh token if you have requested the scope offline_access.

To receive a new set of tokens you need to send a token request with the refresh_token to the token endpoint (See discovery) https://accounts.tam.ch/token. You need to submit the following query parameters:

Parameter Values Description
grant_typerefresh_tokenTo receive a new set of tokens the value „refresh_token“ is needed here
refresh_token refresh_token received in the token response
client_id The client_id you have received during registering your app
client_secret The client_secret you have received during registering your app

As for the access token request you have to authenticate the refresh request using the client authentication method you submitted during the registration of your app.

Example token request:

https://accounts.tam.ch/token with POST parameters grant_type=refresh_token&refresh_token=d1KQFvE-29SO-Es8lPbYhBCXDT2dpWANaKZmE3lBI9A and HTTP header Authorization: Basic base64(my_client_id:my_client_secret) (for client authentication method client_secret_basic)

The response from the authentication server is the same as for the token request above except that it might not contain an id_token.

Use the implicit grant for applications which can not store a client_secret secretly. A good example of such an application is a web SPA (Single page application).

Authentication Request

You need to send a request to the authorization endpoiont (See discovery) https://accounts.tam.ch/auth. You need to submit the following query parameters:

Parameter Values Description
response_typeid_token token The response type, for implicit auth you need „id_token“ or „id_token token“
client_idclient_idYour client_id which you have received during registering your app
redirect_uriURIThe redirect_uri which you submitted during registering your app
scopeopenid profile email intranetScopes to query, you should always request openid and profile. Note: If you want to query an intranet2 API you are required to request the scope intranet as well.
stateRandom StringRandom string to prevent cross-site-request-forgery attacks.
nonceRandom StringRandom string to catch replay attacks.

Example token request:

https://accounts.tam.ch/token?response_type=id_token token&state=551ffbec-40ea-43b0-bb7d-4e509615be55&redirect_uri=https://cloudfs.tam.ch&client_id=my_client_id&scope=openid&nonce=t8+mAHzTW8jGDVjesgxu65HsJFoMdv

If you have a valid shibboleth session, you will get forwarded to your redirect_uri, all parameters from the authorization server are attached after a hashtag (#). If you do not have a valid shibboleth session you will first forwarded to https://aai.tam.ch to authenticate with shibboleth.

Example of a successful response from the authorization server:

https://cloudfs.tam.ch#?access_token=x1D3XM04-xc1avB6cLR8Cco5nCTo-pdc6MDcZHovzII&token_type=Bearer&expires_in=3600&id_token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOlwvXC9hY2NvdW50c2Rldi50YW0uY2hcL29wLmp3ayIsImtpZCI6ImFjY291bnRzZGV2LnRhbS5jaF8wMFMifQ.eyJpc3MiOiJodHRwczpcL1wvYWNjb3VudHNkZXYudGFtLmNoIiwic3ViIjoiMzAzMTMwMzEzMDMxMzAzMTMwMzEzMDMxMzAzMTMwMzFjNzhlMmY1ODI0NjMyNWVkYjUxMWE4Zjc5YTA1ZjkxYjFiYmEzMDgwNjQ4ZmY3MWJhY2U4NTgwNjEyNTM2ZDE3YTVlMzlkNGQwOWUzOTU5MTZhYmQxMDQwNTExNDAwMTcwMDQ5NWI4M2ViNGFhYjFjNWMyNzMyN2Y1ZWYzYjQxZSIsImF1ZCI6WyJsb2NhbC10ZXN0LWFwcCJdLCJleHAiOjE1MDQxMDI0ODYsImlhdCI6MTUwNDEwMjE4Niwibm9uY2UiOiJhYmNkIiwiYXRfaGFzaCI6Im00RTlDWk9uVVpzRmdrcjRqdjctdncifQ.SdS_hcmfcyqUJYhY7h3h7vu7g8gEzORxscdIr4dulAI2cBy7p2am0Lm8zH4p42ajseRwWC9MSTPeTXobLsGAYlLRxEqd1CT5FsVdrCcR6OXH4FtAX3qtXSm1Sna_1E700hMeY9wQ20caSjARYArnsZWMyt7oGnwqA6wHeKJr8bz3gk44vL8cT_wRxrPQumRd0nqx28VFEhrvP2gRa_EWml5bg-cjNqYKYQCbGi8g6bJDuDYju2U0GelwuQEctm8Hbs9xBqNN1uXaBQlO4KIPMhpL_roU0ERxSgaCyS5WBOaxRI8ffwTjKqq5BejokJhCSLfYQo6ILtDDPG8t2qn1ww&state=551ffbec-40ea-43b0-bb7d-4e509615be55

With the access_token you have received above you can now query an API (resource server).

Note that access tokens which are created during implicit auth will expire after 3600s, therefore you are required to the same request for an access_token above again.

JavaScript code example

This code example provides an insight how to authenticate with your AAI and get an access token to query a resource server (CloudFS):

Note that this is not an example for a production use case!

var client = {
OAUTH2_CLIENT_ID: 'xxxxxxxxxxxxxxxxxxxxxxxx',
OAUTH2_REDIRECT_URI: 'https://myapp.example.org',
OAUTH2_AUTH_SERVER: 'https://accounts.tam.ch/token',
OAUTH2_SCOPE: 'openid profile',
CLOUDFS_API:'https://cloudfs.tam.ch/api',
CLOUDFS_API_VERSION: 1,
 
access_token: null,
 
/**
 * Initialize client()
 */
init: function() { this.checkAuth(); },
 
/**
 * Extract Token from URI
 */
extractToken: function(hash) {
    var match = hash.match(/access_token=(\w+)/);
    return !!match && match[1];
},
 
/**
 * Check Access Token
 */
checkAuth: function() {
    this.access_token = this.extractToken(window.location.hash);
    var options = {
        type:'GET',
        url: client.CLOUDFS_API+'/api/auth',
        statusCode: {
            401: function() {
                client.initOauth2();
            },
            403: function() {
                client.initOauth2();
            },
            400: function() {
                client.callCloudfsApi();
            }
        }
    }
 
    if(client.access_token != '') {
        options.headers = { "Authorization": 'Bearer '+client.access_token, }
    }
 
    $.ajax(options);
},
 
/**
 * Forward to tam OAuth2 Authorization Server
 */
initOauth2: function() {
    var nonce = ''(Math.random()*1e32).toString(36);''
    window.location.href = client.OAUTH2_AUTH_SERVER+'/cloudfs?response_type=token&client_id='+
      client.OAUTH2_CLIENT_ID+'&nonce='+nonce+'&redirect_uri='+client.OAUTH2_REDIRECT_URI+'&scope='+<font inherit/inherit;;black;;inherit>encodeURIComponent(</font>client.OAUTH2_SCOPE);
},
 
/**
 * Make an API call to CLOUDFS_API
 */
callCloudfsApi: function() {
    $.ajax({
        url: client.CLOUDFS_API+'/v'+client.CLOUDFS_API_VERSION+'/children',
        type: 'GET',  dataType: 'json',
        statusCode: {
            200: function(data) {
                console.log(data);
            },
            401: function() {
                client.initOauth2();
            }
        },
        headers = {  "Authorization": 'Bearer '+client.access_token,  }
    });
}
}

An endpoint for token introspection is available at https://accounts.tam.ch/introspect (See discovery). The introspection endpoint can be queried with an access_token to check if the token is valid (e.g. for resource servers to verify the token of a user).

Parameter Values Description
tokenaccess_tokenThe access token you want to introspect

Example introspection request:

https://accounts.tam.ch/introspect?token=d-7Amc_P7nyCE25PEcgGEAacff93xAKKianxzFG3TUu

If the token is valid (it exists and is not expired), you receive a JSON document containing some information about the token. In every case the json document contains a key „active“ with a boolean value indicating the validity of the token.

Example introspection response:

active    true
scopes    "openid offline_access"
client_id    my_client_id
username    tamUniqueName
token_type    "bearer"
exp    "1504616611"
iat    "1504528113"
sub    "30313031303130313031303130313031a07275a794dd6feb6b60a5cce43caed2e732b458093495ff08b04eddda32e78911a76e8d47fc079093caba846aa4ff7d"
aud
0    my_client_id
iss    "https://accounts.tam.ch"

An endpoint for token revocation is available at https://accounts.tam.ch/revoke (See discovery). The revocation endpoint can be queried with an access_token or a refresh_token to revoke this token.

Parameter Values Description
tokenyour_tokenThe token (access_token or refresh_token) you want to revoke

Additionally you have to authenticate the token request using the client authentication method you submitted during the registration of your app.

Example revocation request:

https://accounts.tam.ch/revoke?token=d-7Amc_P7nyCE25PEcgGEAacff93xAKKianxzFG3TUu&client_id=my_client_id&client_secret=my_client_secret

If the client credentials were valid, the server responds with a HTTP status 200, meaning the token is revoked.



1)
Artikel wurde aus der Diplomarbeit von Raffael Sahli übernommen, siehe da_sahli_raffael_app_entwicklerdokumentation.pdf
  • 10_public/3rd_party_app_development.1509110557.txt.gz
  • Zuletzt geändert: 2017/10/27 13:22
  • von raffael.sahli