You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -77,12 +77,12 @@ Initially you won't have set which API domains to protect, so the any `addApproo
77
77
Your Approov onboarding email should contain a link allowing you to access [Live Metrics Graphs](https://approov.io/docs/latest/approov-usage-documentation/#metrics-graphs). After you've run your app with Approov integration you should be able to see the results in the live metrics within a minute or so. At this stage you could even release your app to get details of your app population and the attributes of the devices they are running upon.
78
78
79
79
## NEXT STEPS
80
-
To actually protect your APIs there are some further steps. Approov provides two different options for protection:
80
+
To actually protect your APIs and/or secrets there are some further steps. Approov provides two different options for protection:
81
81
82
82
*[API PROTECTION](https://github.com/approov/quickstart-android-java-httpsurlconn/blob/master/API-PROTECTION.md): You should use this if you control the backend API(s) being protected and are able to modify them to ensure that a valid Approov token is being passed by the app. An [Approov Token](https://approov.io/docs/latest/approov-usage-documentation/#approov-tokens) is short lived crytographically signed JWT proving the authenticity of the call.
83
83
84
-
*[SECRETS PROTECTION](https://github.com/approov/quickstart-android-java-httpsurlconn/blob/master/SECRETS-PROTECTION.md): If you do not control the backend API(s) being protected, and are therefore unable to modify it to check Approov tokens, you can use this approach instead. It allows app secrets, and API keys, to be protected so that they no longer need to be included in the built code and are only made available to passing apps at runtime.
84
+
*[SECRETS PROTECTION](https://github.com/approov/quickstart-android-java-httpsurlconn/blob/master/SECRETS-PROTECTION.md): This allows app secrets, including API keys for 3rd party services, to be protected so that they no longer need to be included in the released app code. These secrets are only made available to valid apps at runtime.
85
85
86
-
Note that it is possible to use both approaches side-by-side in the same app, in case your app uses a mixture of 1st and 3rd party APIs.
86
+
Note that it is possible to use both approaches side-by-side in the same app.
87
87
88
88
See [REFERENCE](https://github.com/approov/quickstart-android-java-httpsurlconn/blob/master/REFERENCE.md) for a complete list of all of the `ApproovService` methods.
Copy file name to clipboardExpand all lines: SECRETS-PROTECTION.md
+64-61Lines changed: 64 additions & 61 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,5 @@
1
1
# Secrets Protection
2
-
You should use this option if you wish to protect access to 3rd party or managed APIs where you are not able to add an Approov token check to the backend. This allows client secrets, or API keys, used for access to be protected with Approov. Rather than build secrets into an app where they might be reverse engineered, they are only provided at runtime by Approov for apps that pass attestation. This substantially improves your protection and prevents these secrets being abused by attackers. Where you are able to modify the backend we recommend you use API Protection for further enhanced flexibility and security.
3
-
4
-
This quickstart provides straightforward implementation if the secret is currently supplied in a request header to the API. The `addApproov` method applied to a connection is able to automatically substitute in the secret for headers, but only if the app has passed the Approov attestation checks. If the app fails its checks then you can add a custom [rejection](#handling-rejections) handler.
2
+
You should use this option if you wish to protect app secrets, including API keys. Rather than build secrets into an app, where they might be reverse engineered, they are only provided at runtime by Approov for apps that pass attestation. This substantially improves your protection and prevents these secrets being abused by attackers.
5
3
6
4
These additional steps require access to the [Approov CLI](https://approov.io/docs/latest/approov-cli-tool-reference/), please follow the [Installation](https://approov.io/docs/latest/approov-installation/) instructions.
7
5
@@ -19,7 +17,7 @@ approov pin -setManagedTrustRoots on
19
17
This ensures connections may only use official certificates, and blocks the use of self signed certificates that might be used by a Man-in-the-Middle (MitM) attacker.
20
18
21
19
## ADDING API DOMAINS
22
-
In order for secrets to be protected for particular API domains it is necessary to inform Approov about them. Execute the following command:
20
+
In order for secrets or API keys to be protected when being transmitted externally by the app, it is necessary to inform Approov about the domains on which they may be sent. Execute the following command:
23
21
24
22
```
25
23
approov api -add your.domain -noApproovToken
@@ -33,56 +31,76 @@ It is assumed that you already have some client secrets and/or API keys in your
33
31
```
34
32
approov secstrings -setEnabled
35
33
```
36
-
37
34
> Note that this command requires an [admin role](https://approov.io/docs/latest/approov-usage-documentation/#account-access-roles).
38
35
39
-
The quickstart integration works by allowing you to replace the secret in your app with a placeholder value instead, and then the placeholder value is mapped to the actual secret value by `addApproov`, if the app passes Approov attestation. The shipped app code will only contain the placeholder values.
40
-
41
-
If your app currently uses `your-secret` then replace it in your app with the value `your-secret`. Choose a suitable placeholder name to reflect the type of the secret.
42
-
43
-
You must inform Approov that it should substitute `your-placeholder` with `your-secret` in requests as follows:
36
+
You must inform Approov what the value of each secret is as follows:
> Note that this command also requires an [admin role](https://approov.io/docs/latest/approov-usage-documentation/#account-access-roles).
49
43
50
-
You can add up to 16 different secret values to be substituted in this way.
44
+
These values can be changed at any time and will propagate within 5 minutes to all running instances of your apps. Since earlier released versions of the app may have already leaked `your-secret-value`, you may wish to refresh the secret at some later point when any older version of the app is no longer in use. You can of course do this update over-the-air using Approov without any need to modify the app.
51
45
52
-
If the secret value is provided on the header `your-header` then it is necessary to notify the `ApproovService` that the header is subject to substitution. You do this by making the call once, after initialization:
46
+
You can define up to 16 different secret values in this way.
47
+
48
+
# SUBSTITUTING THE SECRET AUTOMATICALLY
49
+
If the secret is presented in an API header or query parameter, and you are able to use the `ApproovService` networking stack, then Approov can automatically substitute the secret value at runtime. You should use this method wherever possible.
50
+
51
+
If the published code of your app currently uses `your-secret-value` then replace it with the value `your-secret-name`. This provides a placeholder value which can then be automatically substituted with the actual secret value at runtime, for validly attesting apps. The shipped app code will only contain the placeholder values.
52
+
53
+
If the secret value needs to be provided on the header `your-header` then it is necessary to notify the `ApproovService` that the header is subject to substitution. You do this by making the call once, after initialization:
With this in place, calls to `addApproov`should replace the `your-placeholder` with `your-secret` as required when the app passes attestation. Since the mapping lookup is performed on the placeholder value you have the flexibility of providing different secrets on different API calls, even if they are passed with the same header name.
59
+
With this in place the Approov networking interceptor should replace the `your-secret-name` with `your-secret-value` as required when the app passes attestation. Since the mapping lookup is performed on the secret name you have the flexibility of providing different secrets on different API calls, even if they are passed with the same header name.
59
60
60
61
You can see a [worked example](https://github.com/approov/quickstart-android-java-httpsurlconn/blob/master/SHAPES-EXAMPLE.md#shapes-app-with-secrets-protection) for the Shapes app.
61
62
62
-
Since earlier released versions of the app may have already leaked `your-secret`, you may wish to refresh the secret at some later point when any older version of the app is no longer in use. You can of course do this update over-the-air using Approov without any need to modify the app.
63
-
64
63
If the secret value is provided as a parameter in a URL query string then it is necessary to call a function that may rewrite the URL. This must be done before `openConnection()` is called. For instance, if you wish to substitute the parameter `your-param` then you must call:
If no substitution is made then the return value is the same as the input [URL](https://developer.android.com/reference/java/net/URL), otherwise a new `URL` is created with the substituted parameter value. The call should transform any instance of a URL such as `https://your.domain/endpoint?your-param=your-placeholder` into `https://your.domain/endpoint?your-param=your-secret`. Note that this should only ever be applied to a `URL` with a host domain that has been added to Approov, so that either pinning or managed trust roots protection is being applied.
69
+
If no substitution is made then the return value is the same as the input [URL](https://developer.android.com/reference/java/net/URL), otherwise a new `URL` is created with the substituted parameter value. The call should transform any instance of a URL such as `https://your.domain/endpoint?your-param=your-secret-name` into `https://your.domain/endpoint?your-param=your-secret-value`. Note that this should only ever be applied to a `URL` with a host domain that has been added to Approov, so that either pinning or managed trust roots protection is being applied.
71
70
72
-
## REGISTERING APPS
73
-
In order for Approov to recognize the app as being valid it needs to be registered with the service. Change the directory to the top level of your app project and then register the app with Approov:
71
+
## OBTAINING THE SECRET EXPLICITLY
72
+
In some cases it might not be possible to automatically substitute a secret in a header or query parameter. This might be because the secret is used in other ways in your application.
In this case it is possible to make an explicit call at runtime to obtain the secret value, for apps passing attestation. Here is an example for using the required method in `ApproovService`:
78
75
79
-
Note, some versions of Android Studio save the app in `app/build/intermediates/apk/debug/app-debug.apk`.
Note, on Windows you need to substitute \ for / in the above command.
81
+
...
82
82
83
-
> **IMPORTANT:** The registration takes up to 30 seconds to propagate across the Approov Cloud Infrastructure, therefore don't try to run the app again before this time has elapsed. During development of your app you can ensure it [always passes](https://approov.io/docs/latest/approov-usage-documentation/#adding-a-device-security-policy) on your device to not have to register the APK each time you modify it.
84
83
85
-
[Managing Registrations](https://approov.io/docs/latest/approov-usage-documentation/#managing-registrations) provides more details for app registrations, especially for releases to the Play Store. Note that you may also need to apply specific [Android Obfuscation](https://approov.io/docs/latest/approov-usage-documentation/#android-obfuscation) rules for your app when releasing it.
// failure due to the attestation being rejected, e.getARC() and e.getRejectionReasons() may be used to
90
+
// present information to the user (note e.getRejectionReasons() is only available if the feature is
91
+
// enabled, otherwise it is always an empty string)
92
+
}
93
+
catch(ApproovNetworkException e) {
94
+
// failure due to a potentially temporary networking issue, allow for a user initiated retry
95
+
}
96
+
catch(ApproovException e) {
97
+
// a more permanent error, see e.getMessage()
98
+
}
99
+
// use `secret` as required, but never cache or store its value - note `secret` will be null if the provided
100
+
// secret name is not defined
101
+
```
102
+
103
+
> **IMPORTANT:** The secrets obtained should only ever be communicated externally from the app over channels using the Approov networking stack and which have been added as protected API domains. If not then it is possible for them to be intercepted by a Man-in-the-Middle (MitM) attack.
86
104
87
105
## HANDLING REJECTIONS
88
106
If the app is not recognized as being valid by Approov then an `ApproovRejectionException` is thrown on the request and the API call is not completed. The secret value will never be communicated to the app in this case.
@@ -99,6 +117,21 @@ approov policy -setRejectionReasons on
99
117
100
118
You will then be able to use `getRejectionReasons()` on an `ApproovRejectionException` to obtain a comma separated list of [device properties](https://approov.io/docs/latest/approov-usage-documentation/#device-properties) responsible for causing the rejection.
101
119
120
+
## REGISTERING APPS
121
+
In order for Approov to recognize the app as being valid it needs to be registered with the service. Change the directory to the top level of your app project and then register the app with Approov:
Note, some versions of Android Studio save the app in `app/build/intermediates/apk/debug/app-debug.apk`.
128
+
129
+
Note, on Windows you need to substitute \ for / in the above command.
130
+
131
+
> **IMPORTANT:** The registration takes up to 30 seconds to propagate across the Approov Cloud Infrastructure, therefore don't try to run the app again before this time has elapsed. During development of your app you can ensure it [always passes](https://approov.io/docs/latest/approov-usage-documentation/#adding-a-device-security-policy) on your device to not have to register the APK each time you modify it.
132
+
133
+
[Managing Registrations](https://approov.io/docs/latest/approov-usage-documentation/#managing-registrations) provides more details for app registrations, especially for releases to the Play Store. Note that you may also need to apply specific [Android Obfuscation](https://approov.io/docs/latest/approov-usage-documentation/#android-obfuscation) rules for your app when releasing it.
134
+
102
135
## FURTHER OPTIONS
103
136
104
137
See [Exploring Other Approov Features](https://approov.io/docs/latest/approov-usage-documentation/#exploring-other-approov-features) for information about additional Approov features you may wish to try.
This causes the `Bearer` prefix to be stripped before doing the lookup for the substitution, and the `Bearer` prefix added to the actual secret value as part of the substitution.
114
147
115
148
### App Instance Secure Strings
116
-
As shown, it is possible to set predefined secret strings that are only communicated to passing apps. It is also possible to get and set secure string values for each app instance. These are never communicated to the Approov cloud service, but are encrypted at rest using keys which can only be retrieved by passing apps.
117
-
118
-
Here is an example of using the required method in `ApproovService`:
// failure due to the attestation being rejected, e.getARC() and e.getRejectionReasons() may be used to present information to the user
136
-
// (note e.getRejectionReasons() is only available if the feature is enabled, otherwise it is always an empty string)
137
-
}
138
-
catch(ApproovNetworkException e) {
139
-
// failure due to a potentially temporary networking issue, allow for a user initiated retry
140
-
}
141
-
catch(ApproovException e) {
142
-
// a more permanent error, see e.getMessage()
143
-
}
144
-
// use `secret` as required, but never cache or store its value - note `secret` will be null if the provided key is not defined
145
-
```
146
-
147
-
to lookup a secure string with the given `key`, returning `null` if it is not defined. Note that you should never cache this value in your code. Approov does the caching for you in a secure way. You may define a new value for the `key` by passing a new value in `newDef` rather than `null`. An empty string `newDef` is used to delete the secure string.
149
+
In addition to secret values defined in the Approov cloud, it is also possible to get and set secure string values independently for each app instance. These are never communicated to the Approov cloud service, but are encrypted at rest using keys which can only be retrieved by passing apps. You can use this feature to protect user authorization tokens issued to individual apps or other sensitive customer data, for instance.
148
150
149
-
This method is also useful for providing runtime secrets protection when the values are not passed on headers. Secure strings set using this method may be substituted using subsequent `addApproov` calls.
151
+
App instance secure strings can be set and retrived using the [secret fetching code](#obtaining-the-secret-explicitly). You can define a new value for a given secret name by passing a value in the second parameter of `fetchSecureString`, rather than `null`. An empty string may be used to delete the secure string completely.
150
152
151
153
### Prefetching
152
154
If you wish to reduce the latency associated with substituting the first secret, then make this call immediately after initializing `ApproovService`:
@@ -171,8 +173,9 @@ try {
171
173
ApproovService.precheck();
172
174
}
173
175
catch(ApproovRejectionException e) {
174
-
// failure due to the attestation being rejected, e.getARC() and e.getRejectionReasons() may be used to present information to the user
175
-
// (note e.getRejectionReasons() is only available if the feature is enabled, otherwise it is always an empty string)
176
+
// failure due to the attestation being rejected, e.getARC() and e.getRejectionReasons() may be used
177
+
// to present information to the user (note e.getRejectionReasons() is only available if the feature
178
+
// is enabled, otherwise it is always an empty string)
176
179
}
177
180
catch(ApproovNetworkException e) {
178
181
// failure due to a potentially temporary networking issue, allow for a user initiated retry
0 commit comments