Wednesday Jan 29, 2014

Under the covers - Using Mobile OAuth for Native app authentication and Server side Single Sign On

Introduction 

As we roll out OAM's Mobile OAuth functionality and address our customer's use cases around securing native mobile apps accessing OAuth enabled services and APIs, this blog post outlines a real world mobile enterprise extranet use case and unravels the syntax and HTTP requests/responses for OAM's OAuth REST interfaces that are to be used by Mobile OAuth clients with whatever be their mobile platform of choice - iOS or Android.

Use Case

Avitek Retail is a large multi brand retail enterprise. In addition to several other products, Avitek Retail also sells shoes and accessories from different competing brands in their retail outlets. Avitek Retail’s warehouse managers must ensure that adequate inventory levels are maintained to meet customer demand and they typically need access to supplier catalogs to replenish inventory.

Avitek Retail- an Oracle Access Manager customer has built its own inventory replenishment application that is used by its warehouse managers. Avitek Retail originally built its inventory replenishment application as a web based application but has also recently made it available as a mobile native application for both the iOS and Android platforms that can be downloaded from iTunes or the Google Play app stores. In our scenario, ABC Designer Shoe Inc provides a catalog of designer shoes as a REST service that requires a valid OAuth 2.0 access token. This catalog needs to be accessed by Avitek Retail’s Inventory Replenishment application. From an OAuth perspective then we have the following scenario: 

  • OAuth 2.0 Server: Oracle Access Manager 11gR2PS2 deployed at Avitek Retail
  • OAuth 2.0 Client: Avitek Retail’s Inventory Replenishment application
  • OAuth Resource Server: ABC Designer Shoe Catalog
  • Resource Owner: Tom Dole- Warehouse Manager at Avitek Retail who owns the shoe catalog provided by ABC Designer Shoe Inc to Avitek Retail.

Mobile OAuth Flow

Following is the entire mobile flow:

  1. Tom Dole (ABC Shoe Inc Catalog Resource Owner and Avitek Retail Warehouse Manager) attempts to access the Inventory Replenishment application (Mobile OAuth Client)
  2. The Inventory Replenishment application (Mobile OAuth client) requests a pre-authorization code with a device token from the OAM OAuth 2.0 Server.
  3. The OAM OAuth 2.0 Server returns pre-authorization code over APNS(iOS).
  4. The Inventory Replenishment application (Mobile OAuth Client) sends a registration request with device claims and pre-authorization code to the OAM OAuth 2.0 Server. The OAM OAuth 2.0 server uses user-agent redirection, authenticates the user, checks for device security, gets user consent for Mobile OAuth Client registration ( - if Tom Dole is accessing the app for the first time on the mobile device) and returns a client token over APNS/GCM to the Mobile OAuth Client.
  5. The traditional OAuth flow starts now. The OAuth server checks for device security and depending on the configuration, presents the user with a consent page for accessing the ABC Shoe Designer Inc Catalog
  6. The OAM OAuth 2.0 authorization server sends an authorization code to the Inventory Replenishment application (Mobile OAuth client)
  7. The Inventory Replenishment application (Mobile OAuth client) requests for an access token from the OAuth authorization server by sending the authorization code, client token and device claims.
  8. The OAM OAuth 2.0 server returns access token with optional refresh token to the Inventory Replenishment application (Mobile OAuth Client)
  9. The Inventory Replenishment application (Mobile OAuth Client) presents the Access Token to the ABC Shoe Designer Inc Catalog (OAuth 2.0 Resource Server)
  10. The ABC Shoe Designer Inc Catalog (OAuth 2.0 Resource Server) validates the token with the OAM OAuth 2.0 Authorization Server
  11. The ABC Shoe Designer Inc Catalog (OAuth 2.0 Resource Server) provides the requested content to the Inventory Replenishment application (Mobile OAuth Client)

Solution - Under the covers

And here's the secret sauce-- a working sample of the HTTP requests/responses and the syntax of the Mobile OAuth REST interfaces used to enable the Mobile OAuth client application:

Step 1 Create Pre Authorization Code for Client Token
curl -i -H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' -H 'Cache-Control: no-cache, no-store, must-revalidate' --request POST http://slc01mkk.us.oracle.com:14100/ms_oauth/oauth2/endpoints/oauthservice/tokens -d 'grant_type=client_credentials&client_id=1097ae507ea649da81a660293e75d8e2&oracle_device_profile=eyJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6c2RrdmVyc2lvbiI6IjExLjEuMi4wLjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6Z2VvbG9jYXRpb24iOiJMb2NhdGlvbiB1cGRhdGUgZmFpbGVkLExvY2F0aW9uIHVwZGF0ZSBmYWlsZWQiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6bmV0d29ya3R5cGUiOiJXSUZJIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om9zdHlwZSI6ImlQaG9uZSBPUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpwaG9uZWNhcnJpZXJuYW1lIjoiVU5LTk9XTiIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpsb2NhbGUiOiJlbi1VUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpvc3ZlcnNpb24iOiI2LjEiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6amFpbGJyb2tlbiI6ZmFsc2UsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDp2cG5lbmFibGVkIjpmYWxzZSwiaGFyZHdhcmVJZHMiOnsib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50OnVkaWQiOiJFQjY5QzZCOC0yNTJBLTQyOTQtQkYyMy1CQUIwNTU2RkNCMjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6cGhvbmVudW1iZXIiOiJVTktOT1dOIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om1hY2FkZHJlc3MiOiIwMDoxRjo1QjpGNzpDRDo4OSIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDppbWVpIjoiVU5LTk9XTiJ9fQ==&oracle_requested_assertions=oracle-idm%3A%2Foauth%2Fassertion-type%2Fclient-identity%2Fmobile-client-pre-authz-code-client'


Status: 200
{"expires_in":300,"token_type":"Bearer","oracle_tk_context":"pre_azc","access_token":"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGgudGtfY29udGV4dCI6InByZV9hemMiLCJvcmFjbGUub2F1dGgucHJlX2F6Yy50dGMiOiJjbGllbnRfYXNzZXJ0aW9uIiwiZXhwIjoxMzg4OTc5NDc2MDAwLCJpc3MiOiJ3d3cub3JhY2xlLmV4YW1wbGUuY29tIiwicHJuIjpudWxsLCJqdGkiOiI1OTJiNTZhOS1iZmYyLTQxY2YtYWMzMi05NzA3ZWViODAzNmQiLCJvcmFjbGUub2F1dGguY2xpZW50X29yaWdpbl9pZCI6IjEwOTdhZTUwN2VhNjQ5ZGE4MWE2NjAyOTNlNzVkOGUyIiwib3JhY2xlLm9hdXRoLnN2Y19wX24iOiJPQXV0aFNlcnZpY2VQcm9maWxlIiwiaWF0IjoxMzg4OTc5MTc2MDAwLCJvcmFjbGUub2F1dGguaWRfZF9pZCI6IjEyMzQ1Njc4LTEyMzQtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMiIsInVzZXIudGVuYW50Lm5hbWUiOiJEZWZhdWx0RG9tYWluIn0.bp_P6Ub8IVSZ_ABsvHSYmXirTkMd7BkcDBKdvLT1rRZJjmTnt7jXjVGME-QcpEc5crA5FYN0ISSiMvZlC0neQSZ0lYuIS3OdXrBSa5XipBloFsBQt7XJiNcYfywWbJSK_cg9seSZGKsHA5fM72icsm-Oz_SVaa8T0bB6GA3YYnU"}


Step 2 Create Authz code for Client Token
http://slc01mkk.us.oracle.com:14100/ms_oauth/oauth2/endpoints/oauthservice/authorize?client_id=1097ae507ea649da81a660293e75d8e2&response_type=code&redirect_uri=http%3A%2F%2Fslc01mkk.us.oracle.com%3A7001%2Fidmoauthtool%2F&scope=none&oracle_requested_assertions=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&oracle_pre_authz_code=eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGgudGtfY29udGV4dCI6InByZV9hemMiLCJvcmFjbGUub2F1dGgucHJlX2F6Yy50dGMiOiJjbGllbnRfYXNzZXJ0aW9uIiwiZXhwIjoxMzg4OTc5NDc2MDAwLCJpc3MiOiJ3d3cub3JhY2xlLmV4YW1wbGUuY29tIiwicHJuIjpudWxsLCJqdGkiOiI1OTJiNTZhOS1iZmYyLTQxY2YtYWMzMi05NzA3ZWViODAzNmQiLCJvcmFjbGUub2F1dGguY2xpZW50X29yaWdpbl9pZCI6IjEwOTdhZTUwN2VhNjQ5ZGE4MWE2NjAyOTNlNzVkOGUyIiwib3JhY2xlLm9hdXRoLnN2Y19wX24iOiJPQXV0aFNlcnZpY2VQcm9maWxlIiwiaWF0IjoxMzg4OTc5MTc2MDAwLCJvcmFjbGUub2F1dGguaWRfZF9pZCI6IjEyMzQ1Njc4LTEyMzQtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMiIsInVzZXIudGVuYW50Lm5hbWUiOiJEZWZhdWx0RG9tYWluIn0.bp_P6Ub8IVSZ_ABsvHSYmXirTkMd7BkcDBKdvLT1rRZJjmTnt7jXjVGME-QcpEc5crA5FYN0ISSiMvZlC0neQSZ0lYuIS3OdXrBSa5XipBloFsBQt7XJiNcYfywWbJSK_cg9seSZGKsHA5fM72icsm-Oz_SVaa8T0bB6GA3YYnU


Step 3 Create Client Token
curl -i -H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' -H 'Cache-Control: no-cache, no-store, must-revalidate' --request POST http://slc01mkk.us.oracle.com:14100/ms_oauth/oauth2/endpoints/oauthservice/tokens -d 'grant_type=authorization_code&code=eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGgucmVkaXJlY3QtdXJpIjoiaHR0cDovL3NsYzAxbWtrLnVzLm9yYWNsZS5jb206NzAwMS9pZG1vYXV0aHRvb2wvIiwib3JhY2xlLm9hdXRoLmN0LnJlZ191c2VyX2lkX3R5cGUiOiJMREFQX1VJRCIsImlzcyI6Ind3dy5vcmFjbGUuZXhhbXBsZS5jb20iLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6aW1laSI6IlVOS05PV04iLCJvcmFjbGUub2F1dGguc3ZjX3BfbiI6Ik9BdXRoU2VydmljZVByb2ZpbGUiLCJpYXQiOjEzODg5NzkxNzkwMDAsIm9yYWNsZS5vYXV0aC5hemMudHRjIjoiY2xpZW50X2Fzc2VydGlvbiIsIm9yYWNsZS5vYXV0aC50a19jb250ZXh0IjoiYXpjIiwiZXhwIjoxMzg4OTgwMDc5MDAwLCJvcmFjbGUub2F1dGguY3QucmVnX3VzZXIiOiJ3ZWJsb2dpYyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDptYWNhZGRyZXNzIjoiMDA6MUY6NUI6Rjc6Q0Q6ODkiLCJwcm4iOm51bGwsImp0aSI6IjYyNmY2MWVhLTdjODktNGM1MC05NzdmLTVhNThiNmUxNTMzYiIsIm9yYWNsZS5vYXV0aC5jbGllbnRfb3JpZ2luX2lkIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJvcmFjbGUub2F1dGguaWRfZF9pZCI6IjEyMzQ1Njc4LTEyMzQtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMiIsInVzZXIudGVuYW50Lm5hbWUiOiJEZWZhdWx0RG9tYWluIn0.Wm8Xx_lWvq80yLwfThx4rOxwLsDanws0Dzbr3yUdncJe4VBvg0Oz-zGAtNk5i0kjeknyyrt5J3BC7of9NOYYR5dwgwpXMB8uf6qnfdnsxfvX8PFAgsX_rJ68rViFRksghg9Z0juiFPGBE3upBYjawKQXm6bx5UCce6h-N0856wM&client_id=1097ae507ea649da81a660293e75d8e2&redirect_uri=http%3A%2F%2Fslc01mkk.us.oracle.com%3A7001%2Fidmoauthtool%2F&oracle_device_profile=eyJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6c2RrdmVyc2lvbiI6IjExLjEuMi4wLjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6Z2VvbG9jYXRpb24iOiJMb2NhdGlvbiB1cGRhdGUgZmFpbGVkLExvY2F0aW9uIHVwZGF0ZSBmYWlsZWQiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6bmV0d29ya3R5cGUiOiJXSUZJIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om9zdHlwZSI6ImlQaG9uZSBPUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpwaG9uZWNhcnJpZXJuYW1lIjoiVU5LTk9XTiIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpsb2NhbGUiOiJlbi1VUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpvc3ZlcnNpb24iOiI2LjEiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6amFpbGJyb2tlbiI6ZmFsc2UsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDp2cG5lbmFibGVkIjpmYWxzZSwiaGFyZHdhcmVJZHMiOnsib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50OnVkaWQiOiJFQjY5QzZCOC0yNTJBLTQyOTQtQkYyMy1CQUIwNTU2RkNCMjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6cGhvbmVudW1iZXIiOiJVTktOT1dOIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om1hY2FkZHJlc3MiOiIwMDoxRjo1QjpGNzpDRDo4OSIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDppbWVpIjoiVU5LTk9XTiJ9fQ=='


Status: 200
{"oracle_client_assertion_type":"urn:ietf:params:oauth:client-assertion-type:jwt-bearer","expires_in":604800,"token_type":"Bearer","oracle_tk_context":"client_assertion","refresh_token":"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGguY3QucmVnX3VzZXJfaWRfdHlwZSI6IkxEQVBfVUlEIiwiaXNzIjoid3d3Lm9yYWNsZS5leGFtcGxlLmNvbSIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDppbWVpIjoiVU5LTk9XTiIsIm9yYWNsZS5vYXV0aC5ydC50dGMiOiJjbGllbnRfYXNzZXJ0aW9uIiwib3JhY2xlLm9hdXRoLnN2Y19wX24iOiJPQXV0aFNlcnZpY2VQcm9maWxlIiwiaWF0IjoxMzg4OTc5MTkxMDAwLCJvcmFjbGUub2F1dGgudGtfY29udGV4dCI6InJlZnJlc2hfdG9rZW4iLCJleHAiOjEzOTEzOTgzOTEwMDAsIm9yYWNsZS5vYXV0aC5jdC5yZWdfdXNlciI6IndlYmxvZ2ljIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om1hY2FkZHJlc3MiOiIwMDoxRjo1QjpGNzpDRDo4OSIsInBybiI6bnVsbCwianRpIjoiMWUwNTU5N2QtMDRkNy00YjhlLWI4ZTYtYWM5OGFjYzE0OWVlIiwib3JhY2xlLm9hdXRoLmNsaWVudF9vcmlnaW5faWQiOiIxMDk3YWU1MDdlYTY0OWRhODFhNjYwMjkzZTc1ZDhlMiIsInVzZXIudGVuYW50Lm5hbWUiOiJEZWZhdWx0RG9tYWluIiwib3JhY2xlLm9hdXRoLmlkX2RfaWQiOiIxMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwMTIifQ.JvPQIDUffCrC9fv7SpDQmIYMWQJZRjVCxdT_pndOYB4_ET3NpJyiRezGscb8dtLnrmUwISyD0LEwnqPIWd7hAkpXxacvxSaM3OEijDnHRzejVEaZGSPXTlTVuxLKxHb9w_f80E4TIkdSh8nXmW9808wmg9tC7RqDw-pURqmuBvg","access_token":"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGguY3QucmVnX3VzZXJfaWRfdHlwZSI6IkxEQVBfVUlEIiwic3ViIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJpc3MiOiJ3d3cub3JhY2xlLmV4YW1wbGUuY29tIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50OmltZWkiOiJVTktOT1dOIiwib3JhY2xlLm9hdXRoLnN2Y19wX24iOiJPQXV0aFNlcnZpY2VQcm9maWxlIiwiaWF0IjoxMzg4OTc5MTkxMDAwLCJvcmFjbGUub2F1dGgucHJuLmlkX3R5cGUiOiJDbGllbnRJRCIsImV4cCI6MTM4OTU4Mzk5MTAwMCwib3JhY2xlLm9hdXRoLmN0LnJlZ191c2VyIjoid2VibG9naWMiLCJvcmFjbGUub2F1dGgudGtfY29udGV4dCI6ImNsaWVudF9hc3NlcnRpb24iLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6bWFjYWRkcmVzcyI6IjAwOjFGOjVCOkY3OkNEOjg5IiwicHJuIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJqdGkiOiIxYWIyZTg1ZC1lYWM5LTRhMzItODU4MC0xODE5ODhjNDFlZTUiLCJ1c2VyLnRlbmFudC5uYW1lIjoiRGVmYXVsdERvbWFpbiIsIm9yYWNsZS5vYXV0aC5pZF9kX2lkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIn0.aW-Vkkb3YTN6xWOwMHQn0W1drhorC9vW9hTK512_VW0JwYlGd924p9qd4cR1qhJqv802j7NsUPhmra9mYgrKaFrT-aIvPOGHpWcOqu3-tvwkGY7DM_twmRh-jQn_CqHvLpgflbpDYO8KAsp3xyVF6qupM8l2wc4IuQ7hZUMHI5c"}


Step 4 Create Pre Authorization Code for Access Token
curl -i -H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' -H 'Cache-Control: no-cache, no-store, must-revalidate' --request POST http://slc01mkk.us.oracle.com:14100/ms_oauth/oauth2/endpoints/oauthservice/tokens -d 'grant_type=client_credentials&client_id=1097ae507ea649da81a660293e75d8e2&oracle_requested_assertions=oracle-idm%3A%2Foauth%2Fassertion-type%2Fclient-identity%2Fmobile-client-pre-authz-code-access&oracle_device_profile=eyJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6c2RrdmVyc2lvbiI6IjExLjEuMi4wLjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6Z2VvbG9jYXRpb24iOiJMb2NhdGlvbiB1cGRhdGUgZmFpbGVkLExvY2F0aW9uIHVwZGF0ZSBmYWlsZWQiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6bmV0d29ya3R5cGUiOiJXSUZJIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om9zdHlwZSI6ImlQaG9uZSBPUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpwaG9uZWNhcnJpZXJuYW1lIjoiVU5LTk9XTiIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpsb2NhbGUiOiJlbi1VUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpvc3ZlcnNpb24iOiI2LjEiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6amFpbGJyb2tlbiI6ZmFsc2UsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDp2cG5lbmFibGVkIjpmYWxzZSwiaGFyZHdhcmVJZHMiOnsib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50OnVkaWQiOiJFQjY5QzZCOC0yNTJBLTQyOTQtQkYyMy1CQUIwNTU2RkNCMjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6cGhvbmVudW1iZXIiOiJVTktOT1dOIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om1hY2FkZHJlc3MiOiIwMDoxRjo1QjpGNzpDRDo4OSIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDppbWVpIjoiVU5LTk9XTiJ9fQ=='


Status: 200
{"expires_in":300,"token_type":"Bearer","oracle_tk_context":"pre_azc","access_token":"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGgudGtfY29udGV4dCI6InByZV9hemMiLCJleHAiOjEzODg5Nzk0OTIwMDAsImlzcyI6Ind3dy5vcmFjbGUuZXhhbXBsZS5jb20iLCJwcm4iOm51bGwsImp0aSI6ImY0OWQzNmE0LTE4MmItNGE2Yy1iMDY0LWU5Zjc5ZGFlMmFkOCIsIm9yYWNsZS5vYXV0aC5jbGllbnRfb3JpZ2luX2lkIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJvcmFjbGUub2F1dGguc3ZjX3BfbiI6Ik9BdXRoU2VydmljZVByb2ZpbGUiLCJpYXQiOjEzODg5NzkxOTIwMDAsIm9yYWNsZS5vYXV0aC5pZF9kX2lkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIiwidXNlci50ZW5hbnQubmFtZSI6IkRlZmF1bHREb21haW4ifQ.DK5SoC6vndw16EV7o0P1nItngCDH-clwES1fsm6Z7AQTo3eaMbae6q3IChABrN1KsWqUXyzFostpGidsbefvX0zz-ochjP72z9hpnhqkO2ZoQLWC3qK3yQ6tQeSMxJavTJi-HKzJLQ84omTv4-FN9n9kR8anLYvgFG7rB6-XOeo"}


Step 5 Call
http://slc01mkk.us.oracle.com:14100/ms_oauth/oauth2/endpoints/oauthservice/authorize?client_id=1097ae507ea649da81a660293e75d8e2&response_type=code&redirect_uri=http%3A%2F%2Fslc01mkk.us.oracle.com%3A7001%2Fidmoauthtool%2F&scope=UserProfile.users+UserProfile.groups+UserProfile.me+UserProfile.secretkey.management&oracle_pre_authz_code=eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGgudGtfY29udGV4dCI6InByZV9hemMiLCJleHAiOjEzODg5Nzk0OTIwMDAsImlzcyI6Ind3dy5vcmFjbGUuZXhhbXBsZS5jb20iLCJwcm4iOm51bGwsImp0aSI6ImY0OWQzNmE0LTE4MmItNGE2Yy1iMDY0LWU5Zjc5ZGFlMmFkOCIsIm9yYWNsZS5vYXV0aC5jbGllbnRfb3JpZ2luX2lkIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJvcmFjbGUub2F1dGguc3ZjX3BfbiI6Ik9BdXRoU2VydmljZVByb2ZpbGUiLCJpYXQiOjEzODg5NzkxOTIwMDAsIm9yYWNsZS5vYXV0aC5pZF9kX2lkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIiwidXNlci50ZW5hbnQubmFtZSI6IkRlZmF1bHREb21haW4ifQ.DK5SoC6vndw16EV7o0P1nItngCDH-clwES1fsm6Z7AQTo3eaMbae6q3IChABrN1KsWqUXyzFostpGidsbefvX0zz-ochjP72z9hpnhqkO2ZoQLWC3qK3yQ6tQeSMxJavTJi-HKzJLQ84omTv4-FN9n9kR8anLYvgFG7rB6-XOeo


Request an Access Token
curl -i -H 'Accept: */*' --request POST http://slc01mkk.us.oracle.com:14100/ms_oauth/oauth2/endpoints/oauthservice/tokens -d 'grant_type=authorization_code&client_id=1097ae507ea649da81a660293e75d8e2&code=eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGgucmVkaXJlY3QtdXJpIjoiaHR0cDovL3NsYzAxbWtrLnVzLm9yYWNsZS5jb206NzAwMS9pZG1vYXV0aHRvb2wvIiwib3JhY2xlLm9hdXRoLnVzZXJfb3JpZ2luX2lkX3R5cGUiOiJMREFQX1VJRCIsIm9yYWNsZS5vYXV0aC51c2VyX29yaWdpbl9pZCI6IndlYmxvZ2ljIiwiaXNzIjoid3d3Lm9yYWNsZS5leGFtcGxlLmNvbSIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDppbWVpIjoiVU5LTk9XTiIsIm9yYWNsZS5vYXV0aC5zdmNfcF9uIjoiT0F1dGhTZXJ2aWNlUHJvZmlsZSIsImlhdCI6MTM4ODk3OTE5NzAwMCwib3JhY2xlLm9hdXRoLnRrX2NvbnRleHQiOiJhemMiLCJleHAiOjEzODg5ODAwOTcwMDAsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDptYWNhZGRyZXNzIjoiMDA6MUY6NUI6Rjc6Q0Q6ODkiLCJwcm4iOm51bGwsImp0aSI6Ijk2MjVjYWZkLWVkYmUtNDJjNC05ZGMzLWEyMmMyOWMxZTlmZCIsIm9yYWNsZS5vYXV0aC5zY29wZSI6IlVzZXJQcm9maWxlLnNlY3JldGtleS5tYW5hZ2VtZW50IFVzZXJQcm9maWxlLnVzZXJzIFVzZXJQcm9maWxlLm1lIFVzZXJQcm9maWxlLmdyb3VwcyIsIm9yYWNsZS5vYXV0aC5jbGllbnRfb3JpZ2luX2lkIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJ1c2VyLnRlbmFudC5uYW1lIjoiRGVmYXVsdERvbWFpbiIsIm9yYWNsZS5vYXV0aC5pZF9kX2lkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIn0.knflM_0d1NvEZD2Vs5N-piHj-tq3KMNoXLiJkqNTwd73lwAxnwkiy02RLOvyOt3FM05chszQGWl2ahEog7g8tNgTmRG5sDrmLm9HWkpuwqWTStYXf-Sz-thOV3IRU5BN311T-neHb81sq5f6kslqTGvjBnfXXeBzlUDld5DVYVI&oracle_device_profile=eyJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6c2RrdmVyc2lvbiI6IjExLjEuMi4wLjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6Z2VvbG9jYXRpb24iOiJMb2NhdGlvbiB1cGRhdGUgZmFpbGVkLExvY2F0aW9uIHVwZGF0ZSBmYWlsZWQiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6bmV0d29ya3R5cGUiOiJXSUZJIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om9zdHlwZSI6ImlQaG9uZSBPUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpwaG9uZWNhcnJpZXJuYW1lIjoiVU5LTk9XTiIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpsb2NhbGUiOiJlbi1VUyIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDpvc3ZlcnNpb24iOiI2LjEiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6amFpbGJyb2tlbiI6ZmFsc2UsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDp2cG5lbmFibGVkIjpmYWxzZSwiaGFyZHdhcmVJZHMiOnsib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50OnVkaWQiOiJFQjY5QzZCOC0yNTJBLTQyOTQtQkYyMy1CQUIwNTU2RkNCMjAiLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6cGhvbmVudW1iZXIiOiJVTktOT1dOIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50Om1hY2FkZHJlc3MiOiIwMDoxRjo1QjpGNzpDRDo4OSIsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDppbWVpIjoiVU5LTk9XTiJ9fQ==&client_assertion=eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJvcmFjbGUub2F1dGguY3QucmVnX3VzZXJfaWRfdHlwZSI6IkxEQVBfVUlEIiwic3ViIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJpc3MiOiJ3d3cub3JhY2xlLmV4YW1wbGUuY29tIiwib3JhY2xlOmlkbTpjbGFpbXM6Y2xpZW50OmltZWkiOiJVTktOT1dOIiwib3JhY2xlLm9hdXRoLnN2Y19wX24iOiJPQXV0aFNlcnZpY2VQcm9maWxlIiwiaWF0IjoxMzg4OTc5MTkxMDAwLCJvcmFjbGUub2F1dGgucHJuLmlkX3R5cGUiOiJDbGllbnRJRCIsImV4cCI6MTM4OTU4Mzk5MTAwMCwib3JhY2xlLm9hdXRoLmN0LnJlZ191c2VyIjoid2VibG9naWMiLCJvcmFjbGUub2F1dGgudGtfY29udGV4dCI6ImNsaWVudF9hc3NlcnRpb24iLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6bWFjYWRkcmVzcyI6IjAwOjFGOjVCOkY3OkNEOjg5IiwicHJuIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJqdGkiOiIxYWIyZTg1ZC1lYWM5LTRhMzItODU4MC0xODE5ODhjNDFlZTUiLCJ1c2VyLnRlbmFudC5uYW1lIjoiRGVmYXVsdERvbWFpbiIsIm9yYWNsZS5vYXV0aC5pZF9kX2lkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIn0.aW-Vkkb3YTN6xWOwMHQn0W1drhorC9vW9hTK512_VW0JwYlGd924p9qd4cR1qhJqv802j7NsUPhmra9mYgrKaFrT-aIvPOGHpWcOqu3-tvwkGY7DM_twmRh-jQn_CqHvLpgflbpDYO8KAsp3xyVF6qupM8l2wc4IuQ7hZUMHI5c&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&redirect_uri=http%3A%2F%2Fslc01mkk.us.oracle.com%3A7001%2Fidmoauthtool%2F'


Status: 200
{"expires_in":3600,"token_type":"Bearer","access_token":"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6Im9yYWtleSJ9.eyJzdWIiOiJ3ZWJsb2dpYyIsIm9yYWNsZS5vYXV0aC51c2VyX29yaWdpbl9pZF90eXBlIjoiTERBUF9VSUQiLCJvcmFjbGUub2F1dGgudXNlcl9vcmlnaW5faWQiOiJ3ZWJsb2dpYyIsImlzcyI6Ind3dy5vcmFjbGUuZXhhbXBsZS5jb20iLCJvcmFjbGU6aWRtOmNsYWltczpjbGllbnQ6aW1laSI6IlVOS05PV04iLCJvcmFjbGUub2F1dGguc3ZjX3BfbiI6Ik9BdXRoU2VydmljZVByb2ZpbGUiLCJpYXQiOjEzODg5NzkyMDEwMDAsIm9yYWNsZS5vYXV0aC5wcm4uaWRfdHlwZSI6IkxEQVBfVUlEIiwib3JhY2xlLm9hdXRoLnRrX2NvbnRleHQiOiJyZXNvdXJjZV9hY2Nlc3NfdGsiLCJleHAiOjEzODg5ODI4MDEwMDAsIm9yYWNsZTppZG06Y2xhaW1zOmNsaWVudDptYWNhZGRyZXNzIjoiMDA6MUY6NUI6Rjc6Q0Q6ODkiLCJwcm4iOiJ3ZWJsb2dpYyIsImp0aSI6ImQ4ODlkNDVhLTVlNTMtNDllMi1hZDJmLWEwNTI1ZTNlZjY0NiIsIm9yYWNsZS5vYXV0aC5zY29wZSI6IlVzZXJQcm9maWxlLnNlY3JldGtleS5tYW5hZ2VtZW50IFVzZXJQcm9maWxlLnVzZXJzIFVzZXJQcm9maWxlLm1lIFVzZXJQcm9maWxlLmdyb3VwcyIsIm9yYWNsZS5vYXV0aC5jbGllbnRfb3JpZ2luX2lkIjoiMTA5N2FlNTA3ZWE2NDlkYTgxYTY2MDI5M2U3NWQ4ZTIiLCJ1c2VyLnRlbmFudC5uYW1lIjoiRGVmYXVsdERvbWFpbiIsIm9yYWNsZS5vYXV0aC5pZF9kX2lkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIn0.P8YpUfbyTS4jLmVjbtSBG0FJ1BjxRec3iavNDGtG87coqg5QhTaXOJFyuJrVcL68k54acmxN-4gBvAFyQLFwN8fMlGa29iX-vGMO8_o9zq-ggwRlPPxROvvrzkJp_ODW3xdbQuuxhx0X4WBsiUVpCPxCdShqPbJ3sqHf6eeoQSY"}

Monday Jan 20, 2014

The case for Mobile OAuth in the OAM OAuth service

Introduction 

Several OAuth Clients are consumer applications that cannot keep the client secret confidential (application password or private key). These OAuth Clients are called public clients or non-confidential clients. Mobile Client applications i.e. native applications on mobile devices are also categorized as public clients because when a native application is first downloaded from an app store to a device, the client credentials that uniquely identify the client application are baked into the application. Since all users that download the native application have access to the binary, a malicious user could easily decompile the client credentials out of the binary and insert their own credentials. During an OAuth flow when the access code gets exchanged for the access token this leads to a major vulnerability as there is now no secure means of really identifying who is actually receiving and using the access token.

Hence, providing a mechanism to secure the mobile application on the device in order to ensure trusted access is a key requirement specifically for enterprise mobile applications that routinely require access to sensitive data. The OAM OAuth Service provides key features in the OAM OAuth 2.0 Service’s Mobile OAuth flow to facilitate secure enterprise mobile access for OAuth Client applications.

How it's done : Overview - Mobile Application Registration and Mobile Device Identification

The OAM OAuth  Service provides built-in support for a mechanism for mobile applications to be first registered with OAM to use OAuth Access Services. Security is enforced for mobile applications by creating a client profile and issuing client tokens specific to the application on a device. The user provides explicit authorization to register each mobile OAuth application. In the OAM OAuth 2.0 Service, mobile application registration is modeled using the same paradigm as the OAuth protocol flow where mobile application registration is modeled as a scope for which the user needs to provide explicit consent. As a result of the mobile application registration the application is issued a client token. The mobile application always submits this client token as an input parameter for accessing OAM OAuth 2.0 Service end points. Furthermore, the OAM OAuth 2.0 service also allows easy coupling of device identification with mobile application registration where mobile devices and applications can be checked against fraud and security using a built-in integration with Oracle Adaptive Access Manager (OAAM). The mobile application passes device claims along with the client token for accessing OAM OAuth 2.0 Service end points and the OAM OAuth2.0 Service provides a configuration to make certain claims as mandatory and certain claims as optional.

Friday Oct 25, 2013

Using the OAM Mobile & Social SDK to secure native mobile apps - Part 2 : OAM Mobile & Social Server configuration

Objective 
In the second part of this blog post I'll now cover configuration of OAM to secure our sample native apps developed using the iOS SDK. First, here are some key server side concepts:
  • Application Profiles: An application profile is a logical representation of your application within OAM server. It could be a web (html/javascript) or native (iOS or Android) application. Applications may have different requirements for AuthN/AuthZ, and therefore each application that interacts with OAM Mobile & Social REST services must be uniquely defined.
  • Service Providers: Service providers represent the back end services that are accessed by applications. With OAM Mobile & Social these services are in the areas of authentication, authorization and user profile access. A Service Provider then defines a type or class of service for authentication, authorization or user profiles. For example, the JWTAuthentication provider performs authentication and returns JWT (JSON Web Tokens) to the application. In contrast, the OAMAuthentication also provides authentication but uses OAM SSO tokens

  • Service Profiles:  A Service Profile is a logical envelope that defines a service endpoint URL for a service provider for the OAM Mobile & Social Service. You can create multiple service profiles for a service provider to define token capabilities and service endpoints. Each service provider instance requires atleast one corresponding service profile.The  OAM Mobile & Social Service includes a pre-configured service profile for each pre-configured service provider.

  • Service Domains: Service domains bind together application profiles and service profiles with an optional security handler.

    So now let's configure the OAM server. Additional details are in the OAM Documentation and this post simply provides an outline of configuration tasks required to configure OAM for securing native apps. 

    Configuration 

    Create The Application Profile

    Log on to the Oracle Access Management console and from System Configuration -> Mobile and Social -> Mobile Services, select "Create" under Application Profiles. You would do this  step twice - once for each of the native apps - AvitekInventory and AvitekScheduler. Enter the parameters for the new Application profile:

    • Name:  The application name. In this example we use 'InventoryApp' for the AvitekInventory app and 'SchedulerApp' for the AvitekScheduler app. The application name configured here must match the application name in the settings for the deployed iOS application.
    • BaseSecret: Enter a password here. This does not need to match any existing password. It is used as an encryption key between the client and the OAM server. 
    • Mobile Configuration: Enable this checkbox for any mobile applications. This enables the SDK to collect and send Mobile specific attributes to the OAM server. 
    • Webview: Controls the type of browser that the iOS application will use. The embedded browser (default) will render the browser within the application. External will use the system standalone browser. External can sometimes be preferable for debugging
    • URLScheme: The URL scheme associated with the iOS apps that is also used as a custom URL scheme to register O/S handlers that will take control when OAM transfers control to device. For the AvitekInventory and the AvitekScheduler apps I used osa:// and client:// respectively. You set this scheme in Xcode while developing your iOS Apps under Info->URL Types. 
    • Bundle Identifier : The fully qualified name of your iOS application. You typically set this when you create a new Xcode project or under General->Identity in Xcode. For the AvitekInventory and AvitekScheduler apps these were com.us.oracle.AvitekInventory and com.us.oracle.AvitekScheduler respectively

    Create The Service Domain

    Select create under Service domains. Create a name for your domain (AvitekDomain is what I've used). The name configured must match the service domain set in the iOS application settings. Under "Application Profile Selection" click the browse button. Choose the application profiles that you created in the previous step one by one. Set the InventoryApp as the SSO agent (with an automatic priority of 1) and the SchedulerApp as the SSO client. This associates these applications with this service domain and configures them in a 'circle of trust'. 

    Advance to the next page of the wizard to configure the services for this domain. For this example we will use the following services: 

    • Authentication:   This will use the JWT (JSON Web Token) format authentication provider. The iOS application upon successful authentication will receive a signed JWT token from OAM Mobile & Social service. This token will be used in subsequent calls to OAM. Use 'MobileOAMAuthentication' here.

    • Authorization:  The authorization provider. The SDK makes calls to this provider endpoint to obtain authorization decisions on resource requests. Use 'OAMAuthorization' here.

    • User Profile Service:  This is the service that provides user profile services (attribute lookup, attribute modification). It can be any directory configured as a data source in OAM. 

    And that's it! We're done configuring our native apps. In the next section, let's look at some additional features that were mentioned in the earlier post that are automated by the SDK for the app developer i.e. these are areas that require no additional coding by the app developer when developing with the SDK as they only require server side configuration:

    Additional Configuration 
    Offline Authentication

    Select this option in the service domain configuration to allow users to log in and authenticate to the application locally. Clear the box to block users from authenticating locally.

    Strong Authentication

    By simply selecting the OAAMSecurityHandlerPlugin while configuring mobile related Service Domains, the OAM Mobile&Social service allows sophisticated device and client application registration logic as well as the advanced risk and fraud analysis logic found in OAAM to be applied to mobile authentication. Let's look at some scenarios where the OAAMSecurityHandlerPlugin gets used.

    First, when we configure OAM and OAAM to integrate together using the TAP scheme, then that integration kicks off by selecting the OAAMSecurityHandlerPlugin in the mobile service domain. This is how the mobile device is now prompted for KBA,OTP etc depending on the TAP scheme integration and the OAM users registered in the OAAM database. Second, when we configured the service domain, there were claim attributes there that are already pre-configured in OAM Mobile&Social service and we simply accepted the default values- these are the set of attributes that will be fetched from the device and passed to the server during registration/authentication as device profile attributes. When a mobile application requests a token through the Mobile Client SDK, the SDK logic will send the Device Profile attributes as a part of an HTTP request. This set of Device Profile attributes enhances security by creating an audit trail for devices that assists device identification. When the OAAM Security Plug-in is used, a particular combination of Device Profile attribute values is treated as a device finger print, known as the Digital Finger Print in the OAAM Administration Console. Each finger print is assigned a unique fingerprint number. Each OAAM session is associated with a finger print and the finger print makes it possible to log (and audit) the devices that are performing authentication and token acquisition. Finally, if the jail broken option is selected while configuring an application profile, the SDK detects a device is jail broken based on configured policy and if the OAAM handler is configured the plug-in can allow or block access to client device depending on the OAAM policy as well as detect blacklisted, lost or stolen devices and send a wipeout command that deletes all the mobile &social relevant data and blocks the device from future access.

    Social Logins

    Finally, let's complete this post by adding configuration to configure social logins for mobile applications. Although the Avitek sample apps do not demonstrate social logins this would be an ideal exercise for you based on the sample code provided in the earlier post. I'll cover the server side configuration here (with Facebook as an example) and you can retrofit the code to accommodate social logins by following the steps outlined in "Invoking Authentication Services" and add code in LoginViewController and maybe create a new delegate - AvitekRPDelegate based on the description in the previous post.

    So, here all you will need to do is configure an application profile for social login, configure a new service domain that uses the social login application profile, register the app on Facebook and finally configure the Facebook OAuth provider in OAM with those settings. Navigate to Mobile and Social, click on "Internet Identity Services" and create a new application profile. Here are the relevant parameters for the new application profile (-also we're not registering the social user in OAM with this configuration below, however that is a key feature as well):

    • Name:  The application name. This must match the name of the of mobile application profile created for your application under Mobile Services. We used InventoryApp for this example.

    • SharedSecret: Enter a password here. This does not need to match any existing password. It is used as an encryption key between the client and the OAM Mobile and Social service. 

    • Mobile Application Return URL: After the Relying Party (social) login, the OAM Mobile & Social service will redirect to the iOS application using this URI. This is defined under Info->URL type and we used 'osa', so we define this here as 'osa://'

    • Login Type: Choose to allow only internet identity authentication for this exercise.

    • Authentication Service Endpoint : Make sure that /internetidentityauthentication is selected.

    Login to http://developers.facebook.com using your Facebook account and click on Apps and register the app as InventoryApp. Note that the consumer key and API secret gets generated automatically by the Facebook OAuth server. Navigate back to OAM and under Mobile and Social, click on "Internet Identity Services" and edit the Facebook OAuth Provider. Add the consumer key and API secret from the Facebook developers site to the Facebook OAuth Provider:

    Navigate to Mobile Services. Click on New to create a new service domain. In this example we call the domain "AvitekDomainRP". The type should be 'Mobile Application' and the application credential type 'User Token'. Add the application "InventoryApp" to the domain. Advance the next page of the wizard. Select the  default service profiles but ensure that the Authentication Service is set to 'InternetIdentityAuthentication'. Finish the creation of the service domain.


    About

    Kanishk Mahajan is a Principal Product Manager in Oracle Identity Management with product responsibility within the Oracle Access Management suite

    Search

    Categories
    Archives
    « April 2014
    SunMonTueWedThuFriSat
      
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
       
           
    Today