Secured resource access

Resource calls made with the Onegini SDK are always secured with certificate pinning. Payload encryption can be enabled in the Token Server. Debug detection can be configured in the Config Model, if enabled the SDK will verify there is no debugger attached to the app process before fetching the resource. SDK does not perform any mapping or conversion of the response payload. It is up to the App how to process a valid response from the back-end.

Connecting a device

Get resource flow:

1. APP -> SDK: Instruct the SDK to request a resource.
2. SDK -> Resource Gateway: Request a resource at the resource gateway by sending the access token in the request.
3. Resource Gateway -> Token Server: Validate the provided token.
4. Token Server --> Resource Gateway: Details regarding the access token like scope and user, which will be verified by the resource gateway.
5. Resource Gateway -> Resource Server: Get the resource.
6. Resource Server --> Resource Gateway: Return the resource.
7. Resource Gateway --> SDK: Return the resource.
8. SDK --> APP: Resource is returned to the APP which has knowledge of the context of the returned resource.

The SDK can fetch a secure resource in three distinct ways. For a resource that is tied to a user (e.g. account information or transactions), the SDK can execute an authenticated request. For a resource that is tied to an application but are not unique per user, for example application assets, the SDK can execute an anonymous request. For a resource that can be fetched without any additional authentication, but for which you would still like to use certificate pinning and jailbreak/debug detection the SDK can execute an unauthenticated request.

Authenticated requests

Secure resource access is performed using ONGUserClient for authorized calls and ONGDeviceClientfor anonymous calls. Instances can be obtained by using @property (nonatomic, readonly) ONGUserClient *userClient; and @property (nonatomic, readonly) ONGDeviceClient *deviceClient; respectively, or by calling [ONGUserClient sharedInstance]and [ONGDeviceClient sharedInstance] respectively. Attempt to obtain clients instances without configuring the SDK first, will result in throwing NSInternalInconsistencyException exception.

Performing a resource call

For user specific resources the user needs to be authenticated and a token that is connected to the authenticated user is presented to the back-end when fetching a resource.

The SDK requires that the user is authenticated. Fetching user specific resources using the Onegini SDK is done through the following ONGUserClient method:

- (nullable ONGNetworkTask *)fetchResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse * _Nullable response, NSError * _Nullable error))completion;
Example of an authenticated resource call

Objective-C

ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGUserClient sharedInstance] fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
  // handle response
}];

Swift

let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGUserClient.sharedInstance().fetchResource(request) { response, error in
  // handle response
}

Implicit requests

Implicit resource requests are performed using the ONGUserClient. It can be obtained by using the @property (nonatomic, readonly) ONGUserClient *userClient; of the ONGClient object or by calling the +[ONGUserClient sharedInstance] method.

Performing a resource call

Implicit resource calls are authenticated using an implicit access token. It is obtained by the SDK during implicit user authentication. You can find more information about the process in the Implicit authentication guide. Fetching implicit resources using the Onegini SDK is done through the following ONGUserClient method:

- (nullable ONGNetworkTask *)fetchImplicitResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse *_Nullable response, NSError *_Nullable error))completion;
Example of an implicit resource call

Objective-C

ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGUserClient sharedInstance] fetchImplicitResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
  // handle response
}];

Swift

let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGUserClient.sharedInstance().fetchImplicitResource(request) { response, error in
  // handle response
}

Anonymous requests

Secure anonymous resource access is performed using the ONGDeviceClient. It can be obtained by using the @property (nonatomic, readonly) ONGDeviceClient *deviceClient; of the ONGClient object or by calling the +[ONGDeviceClient sharedInstance] method. Any attempt to obtain the ONGDeviceClient without configuring the SDK first, will result in throwing a NSInternalInconsistencyException exception.

Performing a resource call

For anonymous resources a token that is connected to this device is presented to the back-end. Anonymous resource calls allow you to fetch data that is not user specific but should not be publicly available to anybody knowing the API.

The SDK requires the device (application) to be registered, valid and authenticated. Fetching anonymous resources using the Onegini SDK is done through the following ONGDeviceClient method:

- (nullable ONGNetworkTask *)fetchResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse * _Nullable response, NSError * _Nullable error))completion;
Example of an anonymous resource call

Objective-C

ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGDeviceClient sharedInstance] fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
  // handle response
}];

Swift

let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGDeviceClient.sharedInstance().fetchResource(request) { response, error in
  // handle response
}

Unauthenticated requests

Securing unauthenticated requests is performed using the ONGDeviceClient. It can be obtained by using the @property (nonatomic, readonly) ONGDeviceClient *deviceClient; of the ONGClient object or by calling the +[ONGDeviceClient sharedInstance] method. attempt to obtain the ONGDeviceClient without configuring the SDK first, will result in throwing a NSInternalInconsistencyException exception.

Performing a resource call

For unauthenticated requests no token is presented to the back end. Only certificate pinning and jailebreak/debug detection are used when fetching unauthenticated resources. Fetching unauthenticated resources using the Onegini SDK is done through the following ONGDeviceClient method:

- (nullable ONGNetworkTask *)fetchUnauthenticatedResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse * _Nullable response, NSError * _Nullable error))completion;
Example of an unauthenticated resource call

Objective-C

ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGDeviceClient sharedInstance] fetchUnauthenticatedResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
  // handle response
}];

Swift

let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGDeviceClient.sharedInstance().fetchUnauthenticatedResource(request) { response, error in
  // handle response
}

Request Construction

Manual

Both authenticated and anonymous resource calls starts from the ONGResourceRequest construction. The request object combines the following properties:

  • path - URI path, appended to ONGResourceBaseURL set within the ONGClient configuration.
  • method - HTTP request method, can be one of @"GET", @"POST", @"PUT" and @"DELETE".
  • parameters - a dictionary of parameters used for the request. Parameters are appended to the URL or provided within a body depending on the request method (respectively @"GET" or @"POST").
  • parametersEncoding - the encoding used for params, possible values are ONGParametersEncodingJSON, ONGParametersEncodingFormURL or ONGParametersEncodingPropertyList (see ONGResourceRequest.h for the declarations). The default value is ONGParametersEncodingJSON.
  • body - a raw bady of the request. If specified it overwrites the parameters and parametersEncoding.
  • multipartData - the object that represents the multipart data that should be sent. The multipart/form-data Content-Type header is added automatically. Only the HTTP POST method is supported for a multipart request. Note that if you add multipart data the parametersEncoding property is neglected.
  • headers - additional headers added to the HTTP request. The Onegini SDK takes the responsibility of managing the Authorizationand User-Agent headers. These cannot be modified / provided.

In order to create an instance of the ONGResourceRequest you may use one of the built-in initializers:

- (instancetype)initWithPath:(NSString *)path method:(NSString *)method;

- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters;

- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters encoding:(ONGParametersEncoding)encoding;

- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters encoding:(ONGParametersEncoding)encoding headers:(nullable NSDictionary<NSString *, NSString *> *)headers;

- (instancetype)initWithPath:(NSString *)path method:(NSString *)method body:(nullable NSData *)body headers:(nullable NSDictionary<NSString *, NSString *> *)headers;

- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters multipartData:(NSArray<ONGMultipartData *> *)multipartData;

In addition to ONGResourceRequest, which is immutable by design there is a counterpart - ONGMutableResourceRequest that allows you to modify all of the available properties one by one.

Both ONGResourceRequest and ONGMutableResourceRequest conform to the NSCopying and NSMutableCopying protocols for easier usage.

Example of request construction

Objective-C

ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users/" method:@"GET" parameters:@{@"username": @"foo@bar.baz"}];

// mutable version

ONGMutableRequest *request = [[ONGMutableRequest alloc] initWithPath:@"/api/users/" method:@"GET"];
request.headers = @{@"X-Flags": @"1000010"};
request.parameters = @{@"username": @"foo@bar.baz"};
request.parametersEncoding = ONGParametersEncodingJSON;

Swift

let request = ONGResourceRequest(path:"/api/users/" method:"GET" parameters:{"username": "foo@bar.baz"})

// mutable version

let request = ONGMutableRequest(path:@"/api/users/" method:"GET")
request.headers = {"X-Flags": "1000010"}
request.parameters = {"username": "foo@bar.baz"}
request.parametersEncoding = .JSON

Request Builder

In order to simplify request construction the SDK offers a ONGRequestBuilder class, that allow you to build new immutable requests through a set of methods that reflect ONGResourceRequest properties and build an actual request instance by calling the -[ONGRequestBuilder build] method:

@interface ONGRequestBuilder : NSObject

- (instancetype)setMethod:(NSString *)method;
- (instancetype)setPath:(NSString *)path;
- (instancetype)setParameters:(NSDictionary<NSString *, id> *)parameters;
- (instancetype)setParametersEncoding:(ONGParametersEncoding)parametersEncoding;
- (instancetype)setBody:(NSData *)body;
- (instancetype)setMultipartData:(NSArray<ONGMultipartData *> *)multipartData;
- (instancetype)setHeaders:(NSDictionary<NSString *, NSString *> *)headers;

- (ONGResourceRequest *)build;

@end
Example request construction using the builder

Objective-C

ONGResourceRequest *request = [[[[ONGRequestBuilder builder] setMethod:@"GET"] setPath:@"/api/users"] build];

Swift

let request = ONGRequestBuilder().setMethod("GET").setPath("/api/users").setParameters({"username": "foo@bar.baz"}).build()

Handling the resource response

The responsibility for handling the fetched resource response belongs to the completion block passed into fetchResource:completion:. Below you can find the explanation of the two possible outcomes for fetching resources.

Resource call completion

[client fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
  // handle the response
}];

The completion block will be called whenever a fetch resource call is completed. The following values are provided:

  • response - the object containing the status code, headers and the bare data containing the body which needs to be decoded.
  • error - defines the type of error that occurred. Depending on the error reason the following domains are possible: ONGFetchResourceErrorDomain (only for authenticated resource requests), ONGFetchAnonymousResourceErrorDomain (only for anonymous requests), ONGFetchUnauthenticatedResourceDomain (only for unauthenticated resource requests), the ONGGenericErrorDomain in case of a generic error or the NSURLError in case of a http related error.
Example resource call implementation with a JSON encoded payload

Objective-C

[client fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
  if (response && response.statusCode < 400 && response.data) {
    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:body options:0 error:nil];

    // further mapping of JSON

  } else {
    // handle error
  }
}];

Swift

client.fetchResource(request) { response, error in
  if response?.statusCode < 400, let data = response?.data {
    do {
        let json = try NSJSONSerialization.JSONObjectWithData(data, options: [])
        // further response handling

    } catch {
        // response is not JSON encoded
    }

  } else {
    // handle error
  }
}

Handling resource call errors

In case of a resource call failure the SDK will provide an error. Depending on the error reason and resource call type the following domains are possible: ONGFetchResourceErrorDomain (only for authenticated requests), ONGFetchAnonymousResourceErrorDomain (only for anonymous requests), ONGGenericErrorDomain, NSUrlError (in case of http related errors).

Example error handling

Objective-C

[userClient fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
  if (error) {
      switch(error.code) {
        case ONGFetchResourceErrorUserNotAuthenticated:
          // user isn't authenticated
          break;

        case NSURLErrorCancelled:
          // cancelled explicitly, ignore
          break;

        default:
          // default error handling
          break;
    } else {
      // regular response handling
    }
  }
}];

Swift

userClient.fetchResource(request) { response, error in
  if let error = error {
    switch error.code {
    case ONGFetchResourceError.UserNotAuthenticated:
      // user isn't authenticated

    case NSURLError.Cancelled:
      // cancelled explicitly, ignore
      break

    default:
          // default error handling
    }
  } else {
    // regular response handling
  }
}

Running resource call handling

Both authenticated and anonymous resource calls return an instance of the ONGNetworkTask. This object allows you to control and observe the execution by inspecting various properties:

  • state - enum ONGNetworkTaskState, describing whether task is running, suspended, cancelled or completed.
  • identifier - unique task identifier.
  • request - request with which the resource call has been made.
  • response - instance of ONGResourceResponse. This value fulfilled upon request completion and contains useful information like HTTP Status Code, response headers and the actual body of the response. For advanced usage it provides a reference to the NSHTTPURLResponse object.
  • error - instance of NSError fulfilled in case of a request failure. It might be of the NSURLErrorDomain or ONGGenericErrorDomain.

You can control tasks through the following methods:

  • cancel - cancel a running or suspended task.
  • suspend - suspend a running task.
  • resume - resume a suspended task.