By: Jeff E Mandel user 24 Nov 2018 at 3:56 p.m. CST

5 Responses
Jeff E Mandel gravatar
I am trying to secure an iOS app with AppAuth. I added an OpenConnect client, and configured it: ``` Scopes: openid profile Response Types: code Grant Types: authorization_code ``` I created a redirected_url: com.example.myapp://oauth/ where com.example.myapp is my bundle identifier, and a custom URL scheme. I build an authentication request: ``` // builds authentication request OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration clientId:kClientID clientSecret:my_client_password scopes:@[OIDScopeOpenID, OIDScopeProfile] redirectURL:redirect responseType:OIDResponseTypeCode additionalParameters:nil]; // performs authentication request AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; appDelegate.currentAuthorizationFlow = [OIDAuthState authStateByPresentingAuthorizationRequest:request presentingViewController:self callback:^(OIDAuthState *_Nullable authState, NSError *_Nullable error) { if (authState) { NSLog(@"Got authorization tokens. Access token: %@", authState.lastTokenResponse.accessToken); [self setAuthState:authState]; } else { NSLog(@"Authorization error: %@", [error localizedDescription]); self setAuthState:nil]; } }]; }]; ``` This gets me an access token: ``` Got authorization tokens. Access token: 30bdde5b-0430-47c5-a952-c3892eee8c27 ``` in my AppDelegate, I have an NSLog statement: ``` - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *, id> *)options { // Sends the URL to the current authorization flow (if any) which will process it if it relates to // an authorization response. NSLog(@"Redirect"); ``` This never gets called, and it seems like I need to complete the authentication flow from here. Assuming I figure that out, I'm completely confused as to how I enter my user credentials. I'd really like to be able to store them in the keychain and use the thumbprint to access them.

By Jeff E Mandel user 26 Nov 2018 at 7:59 p.m. CST

Jeff E Mandel gravatar
OK, I found out where the call to redirect_uri is occurring, and I think I have a valid token. Now I need to access the api on my server. I have mod_auth_openidc installed (which is how I'm securing my web clients), so I add a Location secured by oauth20. In my ios app, I get what seems to be a valid access token, which I put into the header: ``` Authorization=Bearer 207b24a5-d3ce-4c66-b1c8-5ce5b7fdae4a ``` I configure my introspection endpoint : ``` OIDCOAuthIntrospectionEndpoint https://gluu.example.com/oxauth/restv1/introspection ``` mod_auth_openidc finds the token and the endpoint, and issues a call: ``` https://gluu.example.org/oxauth/restv1/introspection?token=207b24a5-d3ce-4c66-b1c8-5ce5b7fdae4a ``` This fails. If I use curl: ``` curl -k https://gluu.example.com/oxauth/restv1/introspection?token=207b24a5-d3ce-4c66-b1c8-5ce5b7fdae4a {"error":"invalid_request","error_description":"The request is missing a required parameter, includes an unsupported parameter or parameter value, or is otherwise malformed."} ``` Looking at my log: ``` 2018-11-27 01:47:09,996 INFO [qtp1744347043-13] [org.xdi.oxauth.auth.Authenticator] (Authenticator.java:217) - Authentication success for Client: '@!0F72.46D1.7AF3.7752![redacted]' 2018-11-27 01:47:43,997 ERROR [qtp1744347043-16] [xdi.oxauth.introspection.ws.rs.IntrospectionWebService] (IntrospectionWebService.java:123) - Authorization grant is null. ``` So I can see the authentication to get the access token succeeded, but the attempt to use it failed. Any clues?

By Aliaksandr Samuseu staff 27 Nov 2018 at 9:40 a.m. CST

Aliaksandr Samuseu gravatar
Hi, Jeff. 1. For introspection to work, you must add "uma_protection" to the list of allowed scopes for your client's registration entry, and make sure you include this scope in initial request to OP; you don't need to actually adopt or enable UMA, just include this scope 2. The correct introspection request will look like this: ``` POST /oxauth/restv1/introspection HTTP/1.1 Authorization: Bearer 6ed2a554-baa5-4868-b02b-05a33c90c634 Content-Type: application/x-www-form-urlencoded; charset=utf-8 Host: host.example.com Connection: close User-Agent: Paw/3.1.5 (Macintosh; OS X/10.12.6) GCDHTTPRequest Content-Length: 71 token=6ed2a554-baa5-4868-b02b-05a33c90c634&token_type_hint=access_token ``` Note that you use the same token you're trying to introspect in the "Auhorization" header as well.

By Jeff E Mandel user 27 Nov 2018 at 2:08 p.m. CST

Jeff E Mandel gravatar
I changed the registration to add the uma_protection to the scope, and modified AppAuth to include that scope: ``` OIDAuthState: 0x600003f2e760, isAuthorized: YES, refreshToken: "(null)", scope: "openid profile uma_protection", accessToken: "a1db4edb-b49e-4b58-aad5-e75102120fbf", accessTokenExpirationDate: 2018-11-27 19:58:11 +0000, idToken: "eyJraW...[redacted]", lastAuthorizationResponse: <OIDAuthorizationResponse: 0x60000383a710, authorizationCode: b59061e8-4bfd-4c23-b470-4b0d0313ba7e, state: "bKQuTBypeq2Timzo4SAWLwkIVHwezgSMxg4c9oOPqqk", accessToken: "(null)", accessTokenExpirationDate: (null), tokenType: (null), idToken: "(null)", scope: "openid profile uma_protection", additionalParameters: { "session_id" = "362d2453-5e43-4141-85f4-08f4b618c986"; "session_state" = "837c40dc-1ef6-40cf-9942-03051dfac602" ``` I modified my apache configuration for mod_auth_opoenidc: ``` OIDCOAuthIntrospectionEndpointMethod POST OIDCOAuthAcceptTokenAs header post OIDCOAuthIntrospectionEndpointParams token_type_hint=access_token ``` Looking at the apache2/error.log: ``` oidc_util_http_form_encoded_data: data=token_type_hint=access_token&token=a1db4edb-b49e-4b58-aad5-e75102120fbf ``` I'm not sure what I'm doing wrong, but I've read the fine manuals for mod_auth_openidc and gluu, and can't get any further.

By Jeff E Mandel user 27 Nov 2018 at 7:31 p.m. CST

Jeff E Mandel gravatar
I modified my iOS program to emit that POST to the introspection endpoint, and it works: ``` Success: { "acr_values" = "<null>"; active = 1; aud = "@!0F72.46D1.7AF3.7752!0001!2C6D.E329!0008!123B.8DC9.155C.737B"; "client_id" = "@!0F72.46D1.7AF3.7752!0001!2C6D.E329!0008!123B.8DC9.155C.737B"; exp = 1543367992; iat = 1543367692; iss = "https://gluu.example.org"; jti = "<null>"; scopes = ( openid, profile, "uma_protection" ); sub = nLSsSr5oQ4Gk7yHkja9C1xleFfQ2fLgLl9M0WtGT66k; "token_type" = bearer; username = "Jeff E Mandel"; } ``` So all I have to do now is figure out how to get mod_auth_openidc to send that.

By Jeff E Mandel user 29 Nov 2018 at 9:20 a.m. CST

Jeff E Mandel gravatar
I have it working! There are three stars that must be aligned: 1) In AppAuth IOS, nested in a call to performActionWithFreshTokens, get a fresh access_token and add it to the header of an NSURLRequest: ``` NSString *myTokenString = [NSString stringWithFormat:@"Bearer %@", accessToken]; [request setValue:myTokenString forHTTPHeaderField:@"Authorization"]; ``` The request should point at something inside your protected zone, in this case, https://myserver.example.org/myapp 2) In the apache sites_enabled/myserver.conf on example.org, configure mod_auth_openidc for oath20: ``` OIDCOAuthIntrospectionEndpointMethod POST OIDCOAuthAcceptTokenAs header OIDCOAuthIntrospectionEndpointAuth bearer_access_token OIDCOAuthIntrospectionEndpoint https://gluu.example.org/oxauth/restv1/introspection OIDCOAuthIntrospectionClientAuthBearerToken OIDCOAuthIntrospectionEndpointParams token_type_hint=access_token OIDCOAuthIntrospectionTokenParamName token <Location "/myapp"> Require valid-user AuthType oauth20 LogLevel info ProxyPass "http://myserver.example.org:8080/myapp" ProxyPassReverse "http://myserver.example.org:8080/myapp" </Location> ``` Note that bearer_access_token is a relatively recent addition to mod_auth_openidc; I had to upgrade to the latest version to make it work. Also note that I'm redirecting the request to a tomcat servlet running on port 8080 of myserver 3) On gluu.example.org, configure as described in the documentation, but add a scope for uma_protection. I didn't have any luck with PKCE; I resorted to embedding the Client secret in the App. Note that the Client ID/Secret are only used to get the access_token; once you have that, we are authenticating by the access_token, which you can't get without authenticating as a user through the SFSafariView. I'm planning on storing the access_token in the keychain secured by thumprint/facial ID. The version of the App that runs in a browser enforces a logout after every use, as it is "Software as a Medical Device", and users have a tendency to walk away from the hospital computer without having secured their session, but they rarely walk away from their unlocked phone.