federation
2 TopicsSaaS Federation iApp
Problem this snippet solves: f5.saas_idp.v.1.0.1rc1 The official release candidate iApp template has been posted to downloads.f5.com in the RELEASE_CANDIDATE directory of the iApp package. This release has the following changes: Added support for BIG-IP v12.1 Modified the 'SP Initiated?' field in the iApp to 'IdP Initiated?' and the values to 'No, SP only' and 'Yes, IdP and SP' to make this section more clear. f5.saas_idp.v.1.0.0rc1 This release candidate version of the iApp template, released on 4/20/16, provides improved functionality and additional options. The deployment guide has also been substantially updated. f5.saas_idp.v.0.9.0 This iApp allows you to configure F5 BIG-IP Access Policy Manager(APM) as SAML Identity Provider(IdP) to 11 commonly used SaaS applications: Office 365 Salesforce.com Workday Amazon Web Services(limited support) Concur Service-Now Jive Wombat Zendesk WebEx Google Apps How to use this snippet: For information on how to download, install, and use the iApp (and various other prerequisites), see the deployment guide for this configuration: http://f5.com/pdf/deployment-guides/saml-idp-saas-dg.pdf Code : https://downloads.f5.com/esd/product.jsp?sw=BIG-IP&pro=iApp_Templates646Views0likes2CommentsOAuth 2.0 Dynamic Client Registration
Problem this snippet solves: OAuth 2.0 is now supported in version 13. Client applications need to be defined manually in the Web UI. We developed an irule allowing a client application to self register. How to use this snippet: This code makes calls to external functions : json2dict and HTTP Super SIDEBAND Requestor. You need to add them to your set of irules on the BIG-IP before configuring the client app registration service. json2dict proc json2dict JSONtext { string range [ string trim [ string trimleft [ string map {\t {} \n {} \r {} , { } : { } \[ \{ \] \}} $JSONtext ] {\uFEFF} ] ] 1 end-1 } Workflow The client application will do the following request : POST /f5-oauth2/v1/client-register HTTP/1.1 Host: oauthas.example.com User-Agent: curl/7.47.1 Accept: */* Content-Length: 29 Content-Type: application/x-www-form-urlencoded username=user&password=pwd This request can be achieved using cURL : curl -k -vvv https://oauthas.example.com/f5-oauth2/v1/client-register -d 'username=user&password=pwd' Quick notes The irule is configured to create Client Applications with Resource Owner Password Credentials Grant (ROPC) mode activated. The irule needs to be modified to activate other modes Update (2018-05-01) Add a way to configure static client_id and client_secret Update (2018-01-12) URI decode username and password parameters Update (2017-11-07) Use HTTP::collect to workaround issues with large body Update (2017-10-25) Enhance JSON result parsing and attribute retrieval Code : when RULE_INIT { ### # credentials required to access iControl REST API ### set static::adm_user "admin" set static::adm_pwd "admin" ### # settings required to authenticate the user trying to register an application ### set static::timeout 300 set static::lifetime 300 set static::access_profile "/Common/ap-ldap-auth" ### # settings required to update the APM configuration with the newly created ClientApp configuraiton ### set static::adm_partition "Common" set static::oauth_profile "my-oauth-profile" set static::scopes "myscope" ### # settings required to sync the OAuth 2.0 Authorization Server access profile ### set static::oauth_access_policy "ap-oauth-auth-server" ### # settings required to publish the client registration service ### set static::client_register_uri "/f5-oauth2/v1/client-register" set static::host "oauthas.example.com" ### # Define a static client_id and client_secret ### set static::use_static_app 1 set static::client_id "xxxxxxxxxxxxxxxxxxxxxxx" set static::client_secret "xxxxxxxxxxxxxxxxxxx" } when CLIENT_ACCEPTED { ### # When we accept a connection, create an Access session and save the session ID. ### set flow_sid [ACCESS::session create -timeout $static::timeout -lifetime $static::lifetime] } when HTTP_REQUEST { ### # initialize vars ### set username "" set password "" set name "" set client_app "" set scopes "" set client_id "" set client_secret "" set agent "" set timestamp [clock seconds] switch -glob [string tolower [HTTP::header "User-Agent"]] { "*android*" { set agent "android" } "*ios*" { set agent "ios" } default { set agent "default" } } ### # identify client registration request. The client applicaiton needs to do a POST request on client registration URI and provides username and password ### if { [HTTP::path] eq $static::client_register_uri and [HTTP::host] eq $static::host and [HTTP::method] eq "POST" } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_REQUEST_DATA { set username [URI::decode [URI::query "/?$payload" username]] set password [URI::decode [URI::query "/?$payload" password]] ### # play inline ACCESS policy to validate user credentials ### ACCESS::policy evaluate -sid $flow_sid -profile $static::access_profile session.logon.last.username $username session.logon.last.password $password session.server.landinguri [string tolower [HTTP::path]] if { [ACCESS::policy result -sid $flow_sid] eq "deny" or [ACCESS::policy result -sid $flow_sid] eq "not_started" } { HTTP::respond 403 content "{\"error\": \"Invalid user credentials\",\"error-message\": \"Access denied by Acces policy\"}" noserver Content-Type "application/json" Connection Close ACCESS::session remove -sid $flow_sid event disable all } ACCESS::session remove -sid $flow_sid if { !$static::use_static_app } { ### # generate client name and client application name ### set username [string map -nocase { "@" "." } $username] set name "$username-$agent-$timestamp" set client_app $name set scopes $static::scopes ### # prepare and execute API REST call to create a new client application. Endpoint: /mgmt/tm/apm/oauth/oauth-client-app ### set json_body "{\"name\": \"$name\",\"appName\": \"$client_app\",\"authType\": \"secret\",\"grantPassword\": \"enabled\",\"scopes\": \"$scopes\"}" set status [call /Common/HSSR::http_req -state hstate -uri "http://127.0.0.1:8100/mgmt/tm/apm/oauth/oauth-client-app" -method POST -body $json_body -type "application/json; charset=utf-8" -rbody rbody -userid $static::adm_user -passwd $static::adm_pwd ] set json_result [call /Common/sys-exec::json2dict $rbody] if { $status contains "200" } { ### # extract client_id and client_secret from JSON body ### set client_id [lindex $json_result [expr {[lsearch $json_result "clientId"]+1}]] set client_secret [lindex $json_result [expr {[lsearch $json_result "clientSecret"]+1}]] ### # prepare and execute API REST call to bind the client application to the OAuth profile. Endpoint: /mgmt/tm/apm/profile/oauth/~$static::adm_parition~$static::oauth_profile/client-apps ### set json_body "{\"name\": \"$name\"}" set status [call /Common/HSSR::http_req -state hstate -uri "http://127.0.0.1:8100/mgmt/tm/apm/profile/oauth/~$static::adm_partition~$static::oauth_profile/client-apps" -method POST -body $json_body -type "application/json; charset=utf-8" -rbody rbody -userid $static::adm_user -passwd $static::adm_pwd ] set json_result [call /Common/sys-exec::json2dict $rbody] ### # if binding is successful, respond to the client with client_id and client_secret ### if { $status contains "200" } { ### # Prepare and execute API REST call to apply Access Profile after Client Application has been assigned to OAuth profile ### set json_body "{\"generationAction\": \"increment\"}" set status [call /Common/HSSR::http_req -state hstate -uri "http://127.0.0.1:8100/mgmt/tm/apm/profile/access/~$static::adm_partition~$static::oauth_access_policy" -method PATCH -body $json_body -type "application/json; charset=utf-8" -rbody rbody -userid $static::adm_user -passwd $static::adm_pwd ] set json_result [call /Common/sys-exec::json2dict $rbody] if { $status contains "200" } { HTTP::respond 200 content "{\"client_id\": \"$client_id\",\"client_secret\": \"$client_secret\"}" noserver Content-Type "application/json" Connection Close event disable all } else { HTTP::respond 403 content "{\"error\": \"Synchronization failed\",\"error-message\": \"[lindex $json_result 3]\"}" noserver Content-Type "application/json" Connection Close event disable all } } else { HTTP::respond 403 content "{\"error\": \"ClientApp binding failed\",\"error-message\": \"[lindex $json_result 3]\"}" noserver Content-Type "application/json" Connection Close event disable all } } else { HTTP::respond 403 content "{\"error\": \"ClientApp creation failed\",\"error-message\": \"[lindex $json_result 3]\"}" noserver Content-Type "application/json" Connection Close event disable all } } else { HTTP::respond 200 content "{\"client_id\": \"$static::client_id\",\"client_secret\": \"$static::client_secret\"}" noserver Content-Type "application/json" Connection Close event disable all } } Tested this on version: 13.01.2KViews0likes8Comments