├── .gitignore ├── .swift-version ├── LICENSE ├── Rakefile ├── Readme.markdown ├── SharedWebCredentials.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── SharedWebCredentials-iOS.xcscheme ├── SharedWebCredentials ├── Sources │ ├── Credential.swift │ └── Store.swift └── Support │ ├── Info.plist │ └── SharedWebCredentials.h └── docs ├── Structs.html ├── Structs ├── Credential.html └── Store.html ├── badge.svg ├── css ├── highlight.css └── jazzy.css ├── docsets ├── .docset │ └── Contents │ │ ├── Info.plist │ │ └── Resources │ │ ├── Documents │ │ ├── Structs.html │ │ ├── Structs │ │ │ ├── Credential.html │ │ │ └── Store.html │ │ ├── css │ │ │ ├── highlight.css │ │ │ └── jazzy.css │ │ ├── img │ │ │ ├── carat.png │ │ │ ├── dash.png │ │ │ └── gh.png │ │ ├── index.html │ │ ├── js │ │ │ ├── jazzy.js │ │ │ └── jquery.min.js │ │ ├── search.json │ │ └── undocumented.json │ │ └── docSet.dsidx ├── .tgz └── .xml ├── img ├── carat.png ├── dash.png └── gh.png ├── index.html ├── js ├── jazzy.js └── jquery.min.js ├── search.json └── undocumented.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *xcuserdata/ 3 | *.mode1v3 4 | *.pbxuser 5 | *.xcworkspace 6 | build 7 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0.2 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Sam Soffes, https://soff.es 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | desc 'Generate documentation' 2 | task :docs do 3 | sh 'rm -rf docs' 4 | sh 'jazzy \ 5 | --clean \ 6 | --author "Sam Soffes" \ 7 | --author_url https://soff.es \ 8 | --github_url https://github.com/soffes/SharedWebCredentials \ 9 | --github-file-prefix https://github.com/soffes/SharedWebCredentials/tree/`git describe --tags --abbrev=0` \ 10 | --root-url https://soffes.github.io/SharedWebCredentials/ \ 11 | --output docs/' 12 | sh 'rm -rf build' 13 | end 14 | -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | # SharedWebCredentials 2 | 3 | [![Version](https://img.shields.io/github/release/soffes/SharedWebCredentials.svg)](https://github.com/soffes/SharedWebCredentials/releases) 4 | ![Swift Version](https://img.shields.io/badge/swift-3.0.2-orange.svg) 5 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | 7 | Swift library for easily working with Shared Web Credentials for iOS with [Carthage](https://github.com/carthage/carthage) support. 8 | 9 | **[Read the documentation](https://soffes.github.io/SharedWebCredentials/).** 10 | 11 | Released under the [MIT license](LICENSE). Enjoy. 12 | 13 | 14 | ## Installation 15 | 16 | [Carthage](https://github.com/carthage/carthage) is the recommended way to install SharedWebCredentials. Add the following to your Cartfile: 17 | 18 | ``` ruby 19 | github "soffes/SharedWebCredentials" 20 | ``` 21 | 22 | 23 | ## Prerequisites 24 | 25 | To use Shared Web Credentials, you’ll need to setup the proper entitlements and an associated domain. Here’s [documentation](https://developer.apple.com/reference/security/shared_web_credentials) on how to do that. 26 | 27 | Be sure you don’t miss: 28 | 29 | > If your app runs in iOS 9 and later and you use HTTPS to serve the file, you can create a plain text file that uses the application/json MIME type and you don’t need to sign it. 30 | 31 | All of that signing stuff is a real pain. If you are targeting iOS 9 or later, you can skip this step! 32 | 33 | Once you get all of that stuff setup, you can use this framework instead of the Security framework to access the credentials in a Swift-friendly way. 34 | 35 | 36 | ## Usage 37 | 38 | Start by importing the framework: 39 | 40 | ``` swift 41 | import SharedWebCredentials 42 | ``` 43 | 44 | ### Retrieve Credentials 45 | 46 | The system will show its own UI for letting the user choose which account they want to use to sign into the app. The result will be a `Credential` struct or `nil`. 47 | 48 | ``` swift 49 | Store.get { credential, error in 50 | if let credential = credential { 51 | print("Username: \(credential.account), Password: \(credential.password)") 52 | } 53 | 54 | print("Error: \(error)") 55 | } 56 | ``` 57 | 58 | It will automatically use any of the domains you have set in your `com.apple.developer.associated-domains` entitlement. You can optionally specify the `domain` argument to pick a specific one. 59 | 60 | 61 | ### Adding a New Credential 62 | 63 | ``` swift 64 | Store.add(domain: "myapp.com", account: "steve", password: "password") 65 | ``` 66 | 67 | 68 | ### Removing a Credential 69 | 70 | ``` swift 71 | Store.remove(domain: "myapp.com", account: "steve") 72 | ``` 73 | 74 | **[Read the full documentation](https://soffes.github.io/SharedWebCredentials/).** 75 | -------------------------------------------------------------------------------- /SharedWebCredentials.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 21B51D431E8074A70082A5B2 /* Credential.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21B51D3D1E8074A70082A5B2 /* Credential.swift */; }; 11 | 21B51D441E8074A70082A5B2 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21B51D3E1E8074A70082A5B2 /* Store.swift */; }; 12 | 21B51D461E8074A70082A5B2 /* SharedWebCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = 21B51D411E8074A70082A5B2 /* SharedWebCredentials.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXFileReference section */ 16 | 21B51CCF1E805B990082A5B2 /* SharedWebCredentials.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SharedWebCredentials.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | 21B51D3D1E8074A70082A5B2 /* Credential.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Credential.swift; sourceTree = ""; }; 18 | 21B51D3E1E8074A70082A5B2 /* Store.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; 19 | 21B51D401E8074A70082A5B2 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | 21B51D411E8074A70082A5B2 /* SharedWebCredentials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedWebCredentials.h; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 21B51CCB1E805B980082A5B2 /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | ); 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXFrameworksBuildPhase section */ 32 | 33 | /* Begin PBXGroup section */ 34 | 21B51CC51E805B980082A5B2 = { 35 | isa = PBXGroup; 36 | children = ( 37 | 21B51D3B1E8074A70082A5B2 /* SharedWebCredentials */, 38 | 21B51CD01E805B990082A5B2 /* Products */, 39 | ); 40 | sourceTree = ""; 41 | }; 42 | 21B51CD01E805B990082A5B2 /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | 21B51CCF1E805B990082A5B2 /* SharedWebCredentials.framework */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | 21B51D3B1E8074A70082A5B2 /* SharedWebCredentials */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 21B51D3C1E8074A70082A5B2 /* Sources */, 54 | 21B51D3F1E8074A70082A5B2 /* Support */, 55 | ); 56 | path = SharedWebCredentials; 57 | sourceTree = ""; 58 | }; 59 | 21B51D3C1E8074A70082A5B2 /* Sources */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | 21B51D3D1E8074A70082A5B2 /* Credential.swift */, 63 | 21B51D3E1E8074A70082A5B2 /* Store.swift */, 64 | ); 65 | path = Sources; 66 | sourceTree = ""; 67 | }; 68 | 21B51D3F1E8074A70082A5B2 /* Support */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 21B51D401E8074A70082A5B2 /* Info.plist */, 72 | 21B51D411E8074A70082A5B2 /* SharedWebCredentials.h */, 73 | ); 74 | path = Support; 75 | sourceTree = ""; 76 | }; 77 | /* End PBXGroup section */ 78 | 79 | /* Begin PBXHeadersBuildPhase section */ 80 | 21B51CCC1E805B980082A5B2 /* Headers */ = { 81 | isa = PBXHeadersBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | 21B51D461E8074A70082A5B2 /* SharedWebCredentials.h in Headers */, 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXHeadersBuildPhase section */ 89 | 90 | /* Begin PBXNativeTarget section */ 91 | 21B51CCE1E805B980082A5B2 /* SharedWebCredentials-iOS */ = { 92 | isa = PBXNativeTarget; 93 | buildConfigurationList = 21B51CE31E805B990082A5B2 /* Build configuration list for PBXNativeTarget "SharedWebCredentials-iOS" */; 94 | buildPhases = ( 95 | 21B51CCA1E805B980082A5B2 /* Sources */, 96 | 21B51CCB1E805B980082A5B2 /* Frameworks */, 97 | 21B51CCC1E805B980082A5B2 /* Headers */, 98 | 21B51CCD1E805B980082A5B2 /* Resources */, 99 | ); 100 | buildRules = ( 101 | ); 102 | dependencies = ( 103 | ); 104 | name = "SharedWebCredentials-iOS"; 105 | productName = SharedWebCredential; 106 | productReference = 21B51CCF1E805B990082A5B2 /* SharedWebCredentials.framework */; 107 | productType = "com.apple.product-type.framework"; 108 | }; 109 | /* End PBXNativeTarget section */ 110 | 111 | /* Begin PBXProject section */ 112 | 21B51CC61E805B980082A5B2 /* Project object */ = { 113 | isa = PBXProject; 114 | attributes = { 115 | LastSwiftUpdateCheck = 0820; 116 | LastUpgradeCheck = 0820; 117 | ORGANIZATIONNAME = "Sam Soffes"; 118 | TargetAttributes = { 119 | 21B51CCE1E805B980082A5B2 = { 120 | CreatedOnToolsVersion = 8.2.1; 121 | DevelopmentTeam = LHDXBG4XBK; 122 | LastSwiftMigration = 0820; 123 | ProvisioningStyle = Automatic; 124 | }; 125 | }; 126 | }; 127 | buildConfigurationList = 21B51CC91E805B980082A5B2 /* Build configuration list for PBXProject "SharedWebCredentials" */; 128 | compatibilityVersion = "Xcode 3.2"; 129 | developmentRegion = English; 130 | hasScannedForEncodings = 0; 131 | knownRegions = ( 132 | en, 133 | ); 134 | mainGroup = 21B51CC51E805B980082A5B2; 135 | productRefGroup = 21B51CD01E805B990082A5B2 /* Products */; 136 | projectDirPath = ""; 137 | projectRoot = ""; 138 | targets = ( 139 | 21B51CCE1E805B980082A5B2 /* SharedWebCredentials-iOS */, 140 | ); 141 | }; 142 | /* End PBXProject section */ 143 | 144 | /* Begin PBXResourcesBuildPhase section */ 145 | 21B51CCD1E805B980082A5B2 /* Resources */ = { 146 | isa = PBXResourcesBuildPhase; 147 | buildActionMask = 2147483647; 148 | files = ( 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | /* End PBXResourcesBuildPhase section */ 153 | 154 | /* Begin PBXSourcesBuildPhase section */ 155 | 21B51CCA1E805B980082A5B2 /* Sources */ = { 156 | isa = PBXSourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | 21B51D431E8074A70082A5B2 /* Credential.swift in Sources */, 160 | 21B51D441E8074A70082A5B2 /* Store.swift in Sources */, 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXSourcesBuildPhase section */ 165 | 166 | /* Begin XCBuildConfiguration section */ 167 | 21B51CE11E805B990082A5B2 /* Debug */ = { 168 | isa = XCBuildConfiguration; 169 | buildSettings = { 170 | ALWAYS_SEARCH_USER_PATHS = NO; 171 | CLANG_ANALYZER_NONNULL = YES; 172 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 173 | CLANG_CXX_LIBRARY = "libc++"; 174 | CLANG_ENABLE_MODULES = YES; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | CLANG_WARN_BOOL_CONVERSION = YES; 177 | CLANG_WARN_CONSTANT_CONVERSION = YES; 178 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 179 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 180 | CLANG_WARN_EMPTY_BODY = YES; 181 | CLANG_WARN_ENUM_CONVERSION = YES; 182 | CLANG_WARN_INFINITE_RECURSION = YES; 183 | CLANG_WARN_INT_CONVERSION = YES; 184 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 185 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 186 | CLANG_WARN_UNREACHABLE_CODE = YES; 187 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 188 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 189 | COPY_PHASE_STRIP = NO; 190 | CURRENT_PROJECT_VERSION = 1; 191 | DEBUG_INFORMATION_FORMAT = dwarf; 192 | ENABLE_STRICT_OBJC_MSGSEND = YES; 193 | ENABLE_TESTABILITY = YES; 194 | GCC_C_LANGUAGE_STANDARD = gnu99; 195 | GCC_DYNAMIC_NO_PIC = NO; 196 | GCC_NO_COMMON_BLOCKS = YES; 197 | GCC_OPTIMIZATION_LEVEL = 0; 198 | GCC_PREPROCESSOR_DEFINITIONS = ( 199 | "DEBUG=1", 200 | "$(inherited)", 201 | ); 202 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 203 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 204 | GCC_WARN_UNDECLARED_SELECTOR = YES; 205 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 206 | GCC_WARN_UNUSED_FUNCTION = YES; 207 | GCC_WARN_UNUSED_VARIABLE = YES; 208 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 209 | MTL_ENABLE_DEBUG_INFO = YES; 210 | ONLY_ACTIVE_ARCH = YES; 211 | SDKROOT = iphoneos; 212 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 213 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 214 | TARGETED_DEVICE_FAMILY = "1,2"; 215 | VERSIONING_SYSTEM = "apple-generic"; 216 | VERSION_INFO_PREFIX = ""; 217 | }; 218 | name = Debug; 219 | }; 220 | 21B51CE21E805B990082A5B2 /* Release */ = { 221 | isa = XCBuildConfiguration; 222 | buildSettings = { 223 | ALWAYS_SEARCH_USER_PATHS = NO; 224 | CLANG_ANALYZER_NONNULL = YES; 225 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 226 | CLANG_CXX_LIBRARY = "libc++"; 227 | CLANG_ENABLE_MODULES = YES; 228 | CLANG_ENABLE_OBJC_ARC = YES; 229 | CLANG_WARN_BOOL_CONVERSION = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 232 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 233 | CLANG_WARN_EMPTY_BODY = YES; 234 | CLANG_WARN_ENUM_CONVERSION = YES; 235 | CLANG_WARN_INFINITE_RECURSION = YES; 236 | CLANG_WARN_INT_CONVERSION = YES; 237 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 238 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 239 | CLANG_WARN_UNREACHABLE_CODE = YES; 240 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 241 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 242 | COPY_PHASE_STRIP = NO; 243 | CURRENT_PROJECT_VERSION = 1; 244 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 245 | ENABLE_NS_ASSERTIONS = NO; 246 | ENABLE_STRICT_OBJC_MSGSEND = YES; 247 | GCC_C_LANGUAGE_STANDARD = gnu99; 248 | GCC_NO_COMMON_BLOCKS = YES; 249 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 250 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 251 | GCC_WARN_UNDECLARED_SELECTOR = YES; 252 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 253 | GCC_WARN_UNUSED_FUNCTION = YES; 254 | GCC_WARN_UNUSED_VARIABLE = YES; 255 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 256 | MTL_ENABLE_DEBUG_INFO = NO; 257 | SDKROOT = iphoneos; 258 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 259 | TARGETED_DEVICE_FAMILY = "1,2"; 260 | VALIDATE_PRODUCT = YES; 261 | VERSIONING_SYSTEM = "apple-generic"; 262 | VERSION_INFO_PREFIX = ""; 263 | }; 264 | name = Release; 265 | }; 266 | 21B51CE41E805B990082A5B2 /* Debug */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | APPLICATION_EXTENSION_API_ONLY = YES; 270 | CLANG_ENABLE_MODULES = YES; 271 | CODE_SIGN_IDENTITY = ""; 272 | DEFINES_MODULE = YES; 273 | DEVELOPMENT_TEAM = LHDXBG4XBK; 274 | DYLIB_COMPATIBILITY_VERSION = 1; 275 | DYLIB_CURRENT_VERSION = 1; 276 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 277 | INFOPLIST_FILE = "$(SRCROOT)/SharedWebCredentials/Support/Info.plist"; 278 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 279 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 280 | PRODUCT_BUNDLE_IDENTIFIER = com.samsoffes.sharedwebcredentials; 281 | PRODUCT_NAME = SharedWebCredentials; 282 | SKIP_INSTALL = YES; 283 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 284 | SWIFT_VERSION = 3.0.2; 285 | }; 286 | name = Debug; 287 | }; 288 | 21B51CE51E805B990082A5B2 /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | APPLICATION_EXTENSION_API_ONLY = YES; 292 | CLANG_ENABLE_MODULES = YES; 293 | CODE_SIGN_IDENTITY = ""; 294 | DEFINES_MODULE = YES; 295 | DEVELOPMENT_TEAM = LHDXBG4XBK; 296 | DYLIB_COMPATIBILITY_VERSION = 1; 297 | DYLIB_CURRENT_VERSION = 1; 298 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 299 | INFOPLIST_FILE = "$(SRCROOT)/SharedWebCredentials/Support/Info.plist"; 300 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 301 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 302 | PRODUCT_BUNDLE_IDENTIFIER = com.samsoffes.sharedwebcredentials; 303 | PRODUCT_NAME = SharedWebCredentials; 304 | SKIP_INSTALL = YES; 305 | SWIFT_VERSION = 3.0.2; 306 | }; 307 | name = Release; 308 | }; 309 | /* End XCBuildConfiguration section */ 310 | 311 | /* Begin XCConfigurationList section */ 312 | 21B51CC91E805B980082A5B2 /* Build configuration list for PBXProject "SharedWebCredentials" */ = { 313 | isa = XCConfigurationList; 314 | buildConfigurations = ( 315 | 21B51CE11E805B990082A5B2 /* Debug */, 316 | 21B51CE21E805B990082A5B2 /* Release */, 317 | ); 318 | defaultConfigurationIsVisible = 0; 319 | defaultConfigurationName = Release; 320 | }; 321 | 21B51CE31E805B990082A5B2 /* Build configuration list for PBXNativeTarget "SharedWebCredentials-iOS" */ = { 322 | isa = XCConfigurationList; 323 | buildConfigurations = ( 324 | 21B51CE41E805B990082A5B2 /* Debug */, 325 | 21B51CE51E805B990082A5B2 /* Release */, 326 | ); 327 | defaultConfigurationIsVisible = 0; 328 | defaultConfigurationName = Release; 329 | }; 330 | /* End XCConfigurationList section */ 331 | }; 332 | rootObject = 21B51CC61E805B980082A5B2 /* Project object */; 333 | } 334 | -------------------------------------------------------------------------------- /SharedWebCredentials.xcodeproj/xcshareddata/xcschemes/SharedWebCredentials-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /SharedWebCredentials/Sources/Credential.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Credential.swift 3 | // SharedWebCredentials 4 | // 5 | // Created by Sam Soffes on 3/20/17. 6 | // Copyright © 2017 Sam Soffes. All rights reserved. 7 | // 8 | 9 | /// Single credential from Shared Web Credentials Store. 10 | public struct Credential { 11 | 12 | /// Fully qualified domain name of the website 13 | public let domain: String 14 | 15 | /// Account name 16 | public let account: String 17 | 18 | /// Password 19 | public let password: String 20 | 21 | /// Initialize with a result from the Store 22 | init?(dictionary: NSDictionary) { 23 | let dict = dictionary as Dictionary 24 | 25 | guard let domain = dict[kSecAttrServer] as? String, 26 | let account = dict[kSecAttrAccount] as? String, 27 | let password = dict[kSecSharedPassword] as? String 28 | else { return nil } 29 | 30 | self.domain = domain 31 | self.account = account 32 | self.password = password 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SharedWebCredentials/Sources/Store.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Store.swift 3 | // SharedWebCredentials 4 | // 5 | // Created by Sam Soffes on 3/20/17. 6 | // Copyright © 2017 Sam Soffes. All rights reserved. 7 | // 8 | 9 | import Security 10 | 11 | /// 12 | /// Shared Web Credentials Store. 13 | /// 14 | /// Supports reading, adding, and removing shared web credentials. There is also a utility method for generating a new 15 | /// password. 16 | /// 17 | public struct Store { 18 | 19 | // MARK: - Types 20 | 21 | /// 22 | /// Completion block for reading from shared web credentials. 23 | /// 24 | /// - note: If the error is `nil`, the array will not be empty. 25 | /// 26 | /// - parameter credentials: Array of credentials or `nil`. 27 | /// - parameter error: System error or `nil`. 28 | /// 29 | public typealias ReadCompletion = (_ credential: Credential?, _ error: CFError?) -> Void 30 | 31 | /// 32 | /// Completion block for writing to shared web credentials. 33 | /// 34 | /// - note: If the error is `nil`, the operation was a success. 35 | /// 36 | /// - parameter error: System error or `nil`. 37 | /// 38 | public typealias WriteCompletion = (_ error: CFError?) -> Void 39 | 40 | 41 | // MARK: - Accessing Shared Web Credentials 42 | 43 | /// 44 | /// Asynchronously obtain one or more shared passwords for a website. 45 | /// 46 | /// This function requests one or more shared passwords for a given website, depending on whether the optional 47 | /// account parameter is supplied. To obtain results, the website specified in the fqdn parameter must be one which 48 | /// matches an entry in the calling application’s `com.apple.developer.associated-domains` entitlement. 49 | /// 50 | /// - Note: 51 | /// 52 | /// The system API `SecRequestSharedWebCredential` returns an array of `CFDictionary` objects for each result. In 53 | /// practice, you only ever get one dictionary in this array. The system UI shows all of the credentials you have 54 | /// saved, but makes you select just one. The one you select is the contents of the results array. 55 | /// 56 | /// - Parameters: 57 | /// 58 | /// - domain: Fully qualified domain name of the website for which passwords are being requested. If `nil` is 59 | /// passed in this argument, the domain name(s) listed in the calling application’s 60 | /// `com.apple.developer.associated-domains` entitlement are searched implicitly. 61 | /// 62 | /// - account: Account name for which passwords are being requested. The account may be `nil` to request all 63 | /// shared credentials which are available for the site, allowing the caller to discover an existing 64 | /// account. 65 | /// 66 | /// - completion: A block which will be called to deliver the requested credential. If no matching items were 67 | /// found, the credential array will be `nil`, and the CFErrorRef parameter will provide the 68 | /// error result. 69 | /// 70 | public static func get(domain: String? = nil, account: String? = nil, completion: @escaping ReadCompletion) { 71 | let cfDomain = domain.flatMap { $0 as CFString } 72 | let cfAccount = account.flatMap { $0 as CFString } 73 | 74 | SecRequestSharedWebCredential(cfDomain, cfAccount) { array, error in 75 | let credential: Credential? 76 | 77 | if let array = array as Array?, let dictionary = array.first as? NSDictionary { 78 | credential = Credential(dictionary: dictionary) 79 | } else { 80 | credential = nil 81 | } 82 | 83 | completion(credential, error) 84 | } 85 | } 86 | 87 | /// 88 | /// Asynchronously store (or update) a shared password for a website. 89 | /// 90 | /// This function adds a shared password item which will be accessible by Safari and applications that have the 91 | /// specified fully-qualified domain name in their `com.apple.developer.associated-domains` entitlement. If a shared 92 | /// password item already exists for the specified website and account, it will be updated with the provided 93 | /// password. 94 | /// 95 | /// - Note: 96 | /// 97 | /// Since a request involving shared web credentials may potentially require user interaction or other 98 | /// verification to be approved, this function is dispatched asynchronously; your code provides a completion 99 | /// handler that will be called once the results (if any) are available. 100 | /// 101 | /// - Parameters: 102 | /// 103 | /// - domain: The fully qualified domain name of the website requiring the password. 104 | /// 105 | /// - account: The account name associated with this password. 106 | /// 107 | /// - password: The password to be stored. 108 | /// 109 | /// - completion: A block which will be invoked when the function has completed. If the shared password was 110 | /// successfully added, the CFErrorRef parameter passed to the block will be `nil`. If the error 111 | /// parameter is non-nil, an error occurred and the error reference will hold the result. 112 | /// 113 | /// 114 | public static func add(domain: String, account: String, password: String, completion: WriteCompletion? = nil) { 115 | SecAddSharedWebCredential(domain as CFString, account as CFString, password as CFString) { error in 116 | completion?(error) 117 | } 118 | } 119 | 120 | /// 121 | /// Asynchronously remove a shared password for a website. 122 | /// 123 | /// This function remove a shared password item which will be accessible by Safari and applications that have the 124 | /// specified fully-qualified domain name in their `com.apple.developer.associated-domains` entitlement. 125 | /// 126 | /// - Note: 127 | /// 128 | /// Since a request involving shared web credentials may potentially require user interaction or other 129 | /// verification to be approved, this function is dispatched asynchronously; your code provides a completion 130 | /// handler that will be called once the results (if any) are available. 131 | /// 132 | /// - Parameters: 133 | /// 134 | /// - domain: The fully qualified domain name of the website requiring the password. 135 | /// 136 | /// - account: The account name associated with this password. 137 | /// 138 | /// - completion: A block which will be invoked when the function has completed. If the shared password was 139 | /// successfully removed, the CFErrorRef parameter passed to the block will be `nil`. If the error 140 | /// parameter is non-nil, an error occurred and the error reference will hold the result. 141 | /// 142 | /// 143 | public static func remove(domain: String, account: String, completion: WriteCompletion? = nil) { 144 | SecAddSharedWebCredential(domain as CFString, account as CFString, nil) { error in 145 | completion?(error) 146 | } 147 | } 148 | 149 | 150 | // MARK: - Generating Passwords 151 | 152 | /// 153 | /// Returns a randomly generated password. 154 | /// 155 | /// - Returns: 156 | /// 157 | /// Optional `String` password in the form `xxx-xxx-xxx-xxx` where `x` is taken from the sets 158 | /// `"abcdefghkmnopqrstuvwxy"`, `"ABCDEFGHJKLMNPQRSTUVWXYZ"`, `"3456789"` with at least one character from each 159 | /// set being present or `nil` if it failed. 160 | /// 161 | public static func generatePassword() -> String? { 162 | return SecCreateSharedWebCredentialPassword() as String? 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /SharedWebCredentials/Support/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SharedWebCredentials/Support/SharedWebCredentials.h: -------------------------------------------------------------------------------- 1 | // 2 | // SharedWebCredentials.h 3 | // SharedWebCredentials 4 | // 5 | // Created by Sam Soffes on 3/20/17. 6 | // Copyright © 2017 Sam Soffes. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | //! Project version number for SharedWebCredentials. 12 | FOUNDATION_EXPORT double SharedWebCredentialsVersionNumber; 13 | 14 | //! Project version string for SharedWebCredentials. 15 | FOUNDATION_EXPORT const unsigned char SharedWebCredentialsVersionString[]; 16 | -------------------------------------------------------------------------------- /docs/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structs Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |

View on GitHub

18 |

Install in Dash

19 |
20 |
21 |
22 | 27 |
28 |
29 | 44 |
45 |
46 |
47 |

Structs

48 |

The following structs are available globally.

49 | 50 |
51 |
52 |
53 |
    54 |
  • 55 |
    56 | 57 | 58 | 59 | Credential 60 | 61 |
    62 |
    63 |
    64 |
    65 |
    66 |
    67 |

    Single credential from Shared Web Credentials Store.

    68 | 69 | See more 70 |
    71 |
    72 |

    Declaration

    73 |
    74 |

    Swift

    75 |
    public struct Credential
    76 | 77 |
    78 |
    79 |
    80 | Show on GitHub 81 |
    82 |
    83 |
    84 |
  • 85 |
86 |
87 |
88 |
    89 |
  • 90 |
    91 | 92 | 93 | 94 | Store 95 | 96 |
    97 |
    98 |
    99 |
    100 |
    101 |
    102 |

    Shared Web Credentials Store.

    103 | 104 |

    Supports reading, adding, and removing shared web credentials. There is also a utility method for generating a new 105 | password.

    106 | 107 | See more 108 |
    109 |
    110 |

    Declaration

    111 |
    112 |

    Swift

    113 |
    public struct Store
    114 | 115 |
    116 |
    117 |
    118 | Show on GitHub 119 |
    120 |
    121 |
    122 |
  • 123 |
124 |
125 |
126 |
127 | 131 |
132 |
133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /docs/Structs/Credential.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Credential Struct Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |

View on GitHub

19 |

Install in Dash

20 |
21 |
22 |
23 | 28 |
29 |
30 | 45 |
46 |
47 |
48 |

Credential

49 |
50 |
51 |
public struct Credential
52 | 53 |
54 |
55 |

Single credential from Shared Web Credentials Store.

56 | 57 |
58 |
59 |
60 |
    61 |
  • 62 |
    63 | 64 | 65 | 66 | domain 67 | 68 |
    69 |
    70 |
    71 |
    72 |
    73 |
    74 |

    Fully qualified domain name of the website

    75 | 76 |
    77 |
    78 |

    Declaration

    79 |
    80 |

    Swift

    81 |
    public let domain: String
    82 | 83 |
    84 |
    85 |
    86 | Show on GitHub 87 |
    88 |
    89 |
    90 |
  • 91 |
  • 92 |
    93 | 94 | 95 | 96 | account 97 | 98 |
    99 |
    100 |
    101 |
    102 |
    103 |
    104 |

    Account name

    105 | 106 |
    107 |
    108 |

    Declaration

    109 |
    110 |

    Swift

    111 |
    public let account: String
    112 | 113 |
    114 |
    115 |
    116 | Show on GitHub 117 |
    118 |
    119 |
    120 |
  • 121 |
  • 122 |
    123 | 124 | 125 | 126 | password 127 | 128 |
    129 |
    130 |
    131 |
    132 |
    133 |
    134 |

    Password

    135 | 136 |
    137 |
    138 |

    Declaration

    139 |
    140 |

    Swift

    141 |
    public let password: String
    142 | 143 |
    144 |
    145 |
    146 | Show on GitHub 147 |
    148 |
    149 |
    150 |
  • 151 |
152 |
153 |
154 |
155 | 159 |
160 |
161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /docs/Structs/Store.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Store Struct Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |

View on GitHub

19 |

Install in Dash

20 |
21 |
22 |
23 | 28 |
29 |
30 | 45 |
46 |
47 |
48 |

Store

49 |
50 |
51 |
public struct Store
52 | 53 |
54 |
55 |

Shared Web Credentials Store.

56 | 57 |

Supports reading, adding, and removing shared web credentials. There is also a utility method for generating a new 58 | password.

59 | 60 |
61 |
62 |
63 |
64 | 65 | 66 | 67 |

Types

68 |
69 |
70 |
    71 |
  • 72 |
    73 | 74 | 75 | 76 | ReadCompletion 77 | 78 |
    79 |
    80 |
    81 |
    82 |
    83 |
    84 |

    Completion block for reading from shared web credentials.

    85 | 86 |
    87 |

    Note

    88 |

    If the error is nil, the array will not be empty.

    89 | 90 |
    91 | 92 |
    93 |
    94 |

    Declaration

    95 |
    96 |

    Swift

    97 |
    public typealias ReadCompletion = (_ credential: Credential?, _ error: CFError?) -> Void
    98 | 99 |
    100 |
    101 |
    102 |

    Parameters

    103 | 104 | 105 | 106 | 111 | 117 | 118 | 119 | 124 | 130 | 131 | 132 |
    107 | 108 | credentials 109 | 110 | 112 |
    113 |

    Array of credentials or nil.

    114 | 115 |
    116 |
    120 | 121 | error 122 | 123 | 125 |
    126 |

    System error or nil.

    127 | 128 |
    129 |
    133 |
    134 |
    135 | Show on GitHub 136 |
    137 |
    138 |
    139 |
  • 140 |
  • 141 |
    142 | 143 | 144 | 145 | WriteCompletion 146 | 147 |
    148 |
    149 |
    150 |
    151 |
    152 |
    153 |

    Completion block for writing to shared web credentials.

    154 | 155 |
    156 |

    Note

    157 |

    If the error is nil, the operation was a success.

    158 | 159 |
    160 | 161 |
    162 |
    163 |

    Declaration

    164 |
    165 |

    Swift

    166 |
    public typealias WriteCompletion = (_ error: CFError?) -> Void
    167 | 168 |
    169 |
    170 |
    171 |

    Parameters

    172 | 173 | 174 | 175 | 180 | 186 | 187 | 188 |
    176 | 177 | error 178 | 179 | 181 |
    182 |

    System error or nil.

    183 | 184 |
    185 |
    189 |
    190 |
    191 | Show on GitHub 192 |
    193 |
    194 |
    195 |
  • 196 |
197 |
198 |
199 | 206 |
    207 |
  • 208 |
    209 | 210 | 211 | 212 | get(domain:account:completion:) 213 | 214 |
    215 |
    216 |
    217 |
    218 |
    219 |
    220 |

    Asynchronously obtain one or more shared passwords for a website.

    221 | 222 |

    This function requests one or more shared passwords for a given website, depending on whether the optional 223 | account parameter is supplied. To obtain results, the website specified in the fqdn parameter must be one which 224 | matches an entry in the calling application’s com.apple.developer.associated-domains entitlement.

    225 | 226 |
    227 |

    Note

    228 | 229 |
    230 | 231 |

    The system API SecRequestSharedWebCredential returns an array of CFDictionary objects for each result. In 232 | practice, you only ever get one dictionary in this array. The system UI shows all of the credentials you have 233 | saved, but makes you select just one. The one you select is the contents of the results array.

    234 | 235 |
    236 |
    237 |

    Declaration

    238 |
    239 |

    Swift

    240 |
    public static func get(domain: String? = nil, account: String? = nil, completion: @escaping ReadCompletion)
    241 | 242 |
    243 |
    244 |
    245 |

    Parameters

    246 | 247 | 248 | 249 | 254 | 260 | 261 | 262 | 267 | 273 | 274 | 275 | 280 | 286 | 287 | 288 |
    250 | 251 | domain 252 | 253 | 255 |
    256 |

    Fully qualified domain name of the website for which passwords are being requested. If nil is passed in this argument, the domain name(s) listed in the calling application’s com.apple.developer.associated-domains entitlement are searched implicitly.

    257 | 258 |
    259 |
    263 | 264 | account 265 | 266 | 268 |
    269 |

    Account name for which passwords are being requested. The account may be nil to request all shared credentials which are available for the site, allowing the caller to discover an existing account.

    270 | 271 |
    272 |
    276 | 277 | completion 278 | 279 | 281 |
    282 |

    A block which will be called to deliver the requested credential. If no matching items were found, the credential array will be nil, and the CFErrorRef parameter will provide the error result.

    283 | 284 |
    285 |
    289 |
    290 |
    291 | Show on GitHub 292 |
    293 |
    294 |
    295 |
  • 296 |
  • 297 |
    298 | 299 | 300 | 301 | add(domain:account:password:completion:) 302 | 303 |
    304 |
    305 |
    306 |
    307 |
    308 |
    309 |

    Asynchronously store (or update) a shared password for a website.

    310 | 311 |

    This function adds a shared password item which will be accessible by Safari and applications that have the 312 | specified fully-qualified domain name in their com.apple.developer.associated-domains entitlement. If a shared 313 | password item already exists for the specified website and account, it will be updated with the provided 314 | password.

    315 | 316 |
    317 |

    Note

    318 |

    Note:

    319 | 320 |

    Since a request involving shared web credentials may potentially require user interaction or other 321 | verification to be approved, this function is dispatched asynchronously; your code provides a completion 322 | handler that will be called once the results (if any) are available.

    323 | 324 |
    325 | 326 |
    327 |
    328 |

    Declaration

    329 |
    330 |

    Swift

    331 |
    public static func add(domain: String, account: String, password: String, completion: WriteCompletion? = nil)
    332 | 333 |
    334 |
    335 |
    336 |

    Parameters

    337 | 338 | 339 | 340 | 345 | 351 | 352 | 353 | 358 | 364 | 365 | 366 | 371 | 377 | 378 | 379 | 384 | 390 | 391 | 392 |
    341 | 342 | domain 343 | 344 | 346 |
    347 |

    The fully qualified domain name of the website requiring the password.

    348 | 349 |
    350 |
    354 | 355 | account 356 | 357 | 359 |
    360 |

    The account name associated with this password.

    361 | 362 |
    363 |
    367 | 368 | password 369 | 370 | 372 |
    373 |

    The password to be stored.

    374 | 375 |
    376 |
    380 | 381 | completion 382 | 383 | 385 |
    386 |

    A block which will be invoked when the function has completed. If the shared password was successfully added, the CFErrorRef parameter passed to the block will be nil. If the error parameter is non-nil, an error occurred and the error reference will hold the result.

    387 | 388 |
    389 |
    393 |
    394 |
    395 | Show on GitHub 396 |
    397 |
    398 |
    399 |
  • 400 |
  • 401 |
    402 | 403 | 404 | 405 | remove(domain:account:completion:) 406 | 407 |
    408 |
    409 |
    410 |
    411 |
    412 |
    413 |

    Asynchronously remove a shared password for a website.

    414 | 415 |

    This function remove a shared password item which will be accessible by Safari and applications that have the 416 | specified fully-qualified domain name in their com.apple.developer.associated-domains entitlement.

    417 | 418 |
    419 |

    Note

    420 |

    Note:

    421 | 422 |

    Since a request involving shared web credentials may potentially require user interaction or other 423 | verification to be approved, this function is dispatched asynchronously; your code provides a completion 424 | handler that will be called once the results (if any) are available.

    425 | 426 |
    427 | 428 |
    429 |
    430 |

    Declaration

    431 |
    432 |

    Swift

    433 |
    public static func remove(domain: String, account: String, completion: WriteCompletion? = nil)
    434 | 435 |
    436 |
    437 |
    438 |

    Parameters

    439 | 440 | 441 | 442 | 447 | 453 | 454 | 455 | 460 | 466 | 467 | 468 | 473 | 479 | 480 | 481 |
    443 | 444 | domain 445 | 446 | 448 |
    449 |

    The fully qualified domain name of the website requiring the password.

    450 | 451 |
    452 |
    456 | 457 | account 458 | 459 | 461 |
    462 |

    The account name associated with this password.

    463 | 464 |
    465 |
    469 | 470 | completion 471 | 472 | 474 |
    475 |

    A block which will be invoked when the function has completed. If the shared password was successfully removed, the CFErrorRef parameter passed to the block will be nil. If the error parameter is non-nil, an error occurred and the error reference will hold the result.

    476 | 477 |
    478 |
    482 |
    483 |
    484 | Show on GitHub 485 |
    486 |
    487 |
    488 |
  • 489 |
490 |
491 |
492 |
493 | 494 | 495 | 496 |

Generating Passwords

497 |
498 |
499 |
    500 |
  • 501 |
    502 | 503 | 504 | 505 | generatePassword() 506 | 507 |
    508 |
    509 |
    510 |
    511 |
    512 |
    513 |

    Returns a randomly generated password.

    514 | 515 |
    516 |
    517 |

    Declaration

    518 |
    519 |

    Swift

    520 |
    public static func generatePassword() -> String?
    521 | 522 |
    523 |
    524 |
    525 |

    Return Value

    526 |

    Optional String password in the form xxx-xxx-xxx-xxx where x is taken from the sets "abcdefghkmnopqrstuvwxy", "ABCDEFGHJKLMNPQRSTUVWXYZ", "3456789" with at least one character from each set being present or nil if it failed.

    527 | 528 |
    529 |
    530 | Show on GitHub 531 |
    532 |
    533 |
    534 |
  • 535 |
536 |
537 |
538 |
539 | 543 |
544 |
545 | 546 | 547 | 548 | -------------------------------------------------------------------------------- /docs/badge.svg: -------------------------------------------------------------------------------- 1 | documentationdocumentation100%100% -------------------------------------------------------------------------------- /docs/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; 143 | white-space: nowrap; } 144 | .nav-group-task a { 145 | color: #888; } 146 | 147 | .main-content { 148 | background-color: #fff; 149 | border: 1px solid #e2e2e2; 150 | margin-left: 246px; 151 | position: absolute; 152 | overflow: hidden; 153 | padding-bottom: 60px; 154 | top: 70px; 155 | width: 734px; } 156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 157 | margin-bottom: 1em; } 158 | .main-content p { 159 | line-height: 1.8em; } 160 | .main-content section .section:first-child { 161 | margin-top: 0; 162 | padding-top: 0; } 163 | .main-content section .task-group-section .task-group:first-of-type { 164 | padding-top: 10px; } 165 | .main-content section .task-group-section .task-group:first-of-type .section-name { 166 | padding-top: 15px; } 167 | 168 | .section { 169 | padding: 0 25px; } 170 | 171 | .highlight { 172 | background-color: #eee; 173 | padding: 10px 12px; 174 | border: 1px solid #e2e2e2; 175 | border-radius: 4px; 176 | overflow-x: auto; } 177 | 178 | .declaration .highlight { 179 | overflow-x: initial; 180 | padding: 0 40px 40px 0; 181 | margin-bottom: -25px; 182 | background-color: transparent; 183 | border: none; } 184 | 185 | .section-name { 186 | margin: 0; 187 | margin-left: 18px; } 188 | 189 | .task-group-section { 190 | padding-left: 6px; 191 | border-top: 1px solid #e2e2e2; } 192 | 193 | .task-group { 194 | padding-top: 0px; } 195 | 196 | .task-name-container a[name]:before { 197 | content: ""; 198 | display: block; 199 | padding-top: 70px; 200 | margin: -70px 0 0; } 201 | 202 | .item { 203 | padding-top: 8px; 204 | width: 100%; 205 | list-style-type: none; } 206 | .item a[name]:before { 207 | content: ""; 208 | display: block; 209 | padding-top: 70px; 210 | margin: -70px 0 0; } 211 | .item code { 212 | background-color: transparent; 213 | padding: 0; } 214 | .item .token { 215 | padding-left: 3px; 216 | margin-left: 15px; 217 | font-size: 11.9px; } 218 | .item .declaration-note { 219 | font-size: .85em; 220 | color: gray; 221 | font-style: italic; } 222 | 223 | .pointer-container { 224 | border-bottom: 1px solid #e2e2e2; 225 | left: -23px; 226 | padding-bottom: 13px; 227 | position: relative; 228 | width: 110%; } 229 | 230 | .pointer { 231 | background: #f9f9f9; 232 | border-left: 1px solid #e2e2e2; 233 | border-top: 1px solid #e2e2e2; 234 | height: 12px; 235 | left: 21px; 236 | top: -7px; 237 | -webkit-transform: rotate(45deg); 238 | -moz-transform: rotate(45deg); 239 | -o-transform: rotate(45deg); 240 | transform: rotate(45deg); 241 | position: absolute; 242 | width: 12px; } 243 | 244 | .height-container { 245 | display: none; 246 | left: -25px; 247 | padding: 0 25px; 248 | position: relative; 249 | width: 100%; 250 | overflow: hidden; } 251 | .height-container .section { 252 | background: #f9f9f9; 253 | border-bottom: 1px solid #e2e2e2; 254 | left: -25px; 255 | position: relative; 256 | width: 100%; 257 | padding-top: 10px; 258 | padding-bottom: 5px; } 259 | 260 | .aside, .language { 261 | padding: 6px 12px; 262 | margin: 12px 0; 263 | border-left: 5px solid #dddddd; 264 | overflow-y: hidden; } 265 | .aside .aside-title, .language .aside-title { 266 | font-size: 9px; 267 | letter-spacing: 2px; 268 | text-transform: uppercase; 269 | padding-bottom: 0; 270 | margin: 0; 271 | color: #aaa; 272 | -webkit-user-select: none; } 273 | .aside p:last-child, .language p:last-child { 274 | margin-bottom: 0; } 275 | 276 | .language { 277 | border-left: 5px solid #cde9f4; } 278 | .language .aside-title { 279 | color: #4b8afb; } 280 | 281 | .aside-warning { 282 | border-left: 5px solid #ff6666; } 283 | .aside-warning .aside-title { 284 | color: #ff0000; } 285 | 286 | .graybox { 287 | border-collapse: collapse; 288 | width: 100%; } 289 | .graybox p { 290 | margin: 0; 291 | word-break: break-word; 292 | min-width: 50px; } 293 | .graybox td { 294 | border: 1px solid #e2e2e2; 295 | padding: 5px 25px 5px 10px; 296 | vertical-align: middle; } 297 | .graybox tr td:first-of-type { 298 | text-align: right; 299 | padding: 7px; 300 | vertical-align: top; 301 | word-break: normal; 302 | width: 40px; } 303 | 304 | .slightly-smaller { 305 | font-size: 0.9em; } 306 | 307 | #footer { 308 | position: absolute; 309 | bottom: 10px; 310 | margin-left: 25px; } 311 | #footer p { 312 | margin: 0; 313 | color: #aaa; 314 | font-size: 0.8em; } 315 | 316 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 317 | display: none; } 318 | html.dash .main-content { 319 | width: 980px; 320 | margin-left: 0; 321 | border: none; 322 | width: 100%; 323 | top: 0; 324 | padding-bottom: 0; } 325 | html.dash .height-container { 326 | display: block; } 327 | html.dash .item .token { 328 | margin-left: 0; } 329 | html.dash .content-wrapper { 330 | width: auto; } 331 | html.dash #footer { 332 | position: static; } 333 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | com.jazzy. 7 | CFBundleName 8 | 9 | DocSetPlatformFamily 10 | 11 | isDashDocset 12 | 13 | dashIndexFilePath 14 | index.html 15 | isJavaScriptEnabled 16 | 17 | DashDocSetFamily 18 | dashtoc 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structs Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |

View on GitHub

18 |

Install in Dash

19 |
20 |
21 |
22 | 27 |
28 |
29 | 44 |
45 |
46 |
47 |

Structs

48 |

The following structs are available globally.

49 | 50 |
51 |
52 |
53 |
    54 |
  • 55 |
    56 | 57 | 58 | 59 | Credential 60 | 61 |
    62 |
    63 |
    64 |
    65 |
    66 |
    67 |

    Single credential from Shared Web Credentials Store.

    68 | 69 | See more 70 |
    71 |
    72 |

    Declaration

    73 |
    74 |

    Swift

    75 |
    public struct Credential
    76 | 77 |
    78 |
    79 |
    80 | Show on GitHub 81 |
    82 |
    83 |
    84 |
  • 85 |
86 |
87 |
88 |
    89 |
  • 90 |
    91 | 92 | 93 | 94 | Store 95 | 96 |
    97 |
    98 |
    99 |
    100 |
    101 |
    102 |

    Shared Web Credentials Store.

    103 | 104 |

    Supports reading, adding, and removing shared web credentials. There is also a utility method for generating a new 105 | password.

    106 | 107 | See more 108 |
    109 |
    110 |

    Declaration

    111 |
    112 |

    Swift

    113 |
    public struct Store
    114 | 115 |
    116 |
    117 |
    118 | Show on GitHub 119 |
    120 |
    121 |
    122 |
  • 123 |
124 |
125 |
126 |
127 | 131 |
132 |
133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs/Credential.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Credential Struct Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |

View on GitHub

19 |

Install in Dash

20 |
21 |
22 |
23 | 28 |
29 |
30 | 45 |
46 |
47 |
48 |

Credential

49 |
50 |
51 |
public struct Credential
52 | 53 |
54 |
55 |

Single credential from Shared Web Credentials Store.

56 | 57 |
58 |
59 |
60 |
    61 |
  • 62 |
    63 | 64 | 65 | 66 | domain 67 | 68 |
    69 |
    70 |
    71 |
    72 |
    73 |
    74 |

    Fully qualified domain name of the website

    75 | 76 |
    77 |
    78 |

    Declaration

    79 |
    80 |

    Swift

    81 |
    public let domain: String
    82 | 83 |
    84 |
    85 |
    86 | Show on GitHub 87 |
    88 |
    89 |
    90 |
  • 91 |
  • 92 |
    93 | 94 | 95 | 96 | account 97 | 98 |
    99 |
    100 |
    101 |
    102 |
    103 |
    104 |

    Account name

    105 | 106 |
    107 |
    108 |

    Declaration

    109 |
    110 |

    Swift

    111 |
    public let account: String
    112 | 113 |
    114 |
    115 |
    116 | Show on GitHub 117 |
    118 |
    119 |
    120 |
  • 121 |
  • 122 |
    123 | 124 | 125 | 126 | password 127 | 128 |
    129 |
    130 |
    131 |
    132 |
    133 |
    134 |

    Password

    135 | 136 |
    137 |
    138 |

    Declaration

    139 |
    140 |

    Swift

    141 |
    public let password: String
    142 | 143 |
    144 |
    145 |
    146 | Show on GitHub 147 |
    148 |
    149 |
    150 |
  • 151 |
152 |
153 |
154 |
155 | 159 |
160 |
161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs/Store.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Store Struct Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |

View on GitHub

19 |

Install in Dash

20 |
21 |
22 |
23 | 28 |
29 |
30 | 45 |
46 |
47 |
48 |

Store

49 |
50 |
51 |
public struct Store
52 | 53 |
54 |
55 |

Shared Web Credentials Store.

56 | 57 |

Supports reading, adding, and removing shared web credentials. There is also a utility method for generating a new 58 | password.

59 | 60 |
61 |
62 |
63 |
64 | 65 | 66 | 67 |

Types

68 |
69 |
70 |
    71 |
  • 72 |
    73 | 74 | 75 | 76 | ReadCompletion 77 | 78 |
    79 |
    80 |
    81 |
    82 |
    83 |
    84 |

    Completion block for reading from shared web credentials.

    85 | 86 |
    87 |

    Note

    88 |

    If the error is nil, the array will not be empty.

    89 | 90 |
    91 | 92 |
    93 |
    94 |

    Declaration

    95 |
    96 |

    Swift

    97 |
    public typealias ReadCompletion = (_ credential: Credential?, _ error: CFError?) -> Void
    98 | 99 |
    100 |
    101 |
    102 |

    Parameters

    103 | 104 | 105 | 106 | 111 | 117 | 118 | 119 | 124 | 130 | 131 | 132 |
    107 | 108 | credentials 109 | 110 | 112 |
    113 |

    Array of credentials or nil.

    114 | 115 |
    116 |
    120 | 121 | error 122 | 123 | 125 |
    126 |

    System error or nil.

    127 | 128 |
    129 |
    133 |
    134 |
    135 | Show on GitHub 136 |
    137 |
    138 |
    139 |
  • 140 |
  • 141 |
    142 | 143 | 144 | 145 | WriteCompletion 146 | 147 |
    148 |
    149 |
    150 |
    151 |
    152 |
    153 |

    Completion block for writing to shared web credentials.

    154 | 155 |
    156 |

    Note

    157 |

    If the error is nil, the operation was a success.

    158 | 159 |
    160 | 161 |
    162 |
    163 |

    Declaration

    164 |
    165 |

    Swift

    166 |
    public typealias WriteCompletion = (_ error: CFError?) -> Void
    167 | 168 |
    169 |
    170 |
    171 |

    Parameters

    172 | 173 | 174 | 175 | 180 | 186 | 187 | 188 |
    176 | 177 | error 178 | 179 | 181 |
    182 |

    System error or nil.

    183 | 184 |
    185 |
    189 |
    190 |
    191 | Show on GitHub 192 |
    193 |
    194 |
    195 |
  • 196 |
197 |
198 |
199 | 206 |
    207 |
  • 208 |
    209 | 210 | 211 | 212 | get(domain:account:completion:) 213 | 214 |
    215 |
    216 |
    217 |
    218 |
    219 |
    220 |

    Asynchronously obtain one or more shared passwords for a website.

    221 | 222 |

    This function requests one or more shared passwords for a given website, depending on whether the optional 223 | account parameter is supplied. To obtain results, the website specified in the fqdn parameter must be one which 224 | matches an entry in the calling application’s com.apple.developer.associated-domains entitlement.

    225 | 226 |
    227 |

    Note

    228 | 229 |
    230 | 231 |

    The system API SecRequestSharedWebCredential returns an array of CFDictionary objects for each result. In 232 | practice, you only ever get one dictionary in this array. The system UI shows all of the credentials you have 233 | saved, but makes you select just one. The one you select is the contents of the results array.

    234 | 235 |
    236 |
    237 |

    Declaration

    238 |
    239 |

    Swift

    240 |
    public static func get(domain: String? = nil, account: String? = nil, completion: @escaping ReadCompletion)
    241 | 242 |
    243 |
    244 |
    245 |

    Parameters

    246 | 247 | 248 | 249 | 254 | 260 | 261 | 262 | 267 | 273 | 274 | 275 | 280 | 286 | 287 | 288 |
    250 | 251 | domain 252 | 253 | 255 |
    256 |

    Fully qualified domain name of the website for which passwords are being requested. If nil is passed in this argument, the domain name(s) listed in the calling application’s com.apple.developer.associated-domains entitlement are searched implicitly.

    257 | 258 |
    259 |
    263 | 264 | account 265 | 266 | 268 |
    269 |

    Account name for which passwords are being requested. The account may be nil to request all shared credentials which are available for the site, allowing the caller to discover an existing account.

    270 | 271 |
    272 |
    276 | 277 | completion 278 | 279 | 281 |
    282 |

    A block which will be called to deliver the requested credential. If no matching items were found, the credential array will be nil, and the CFErrorRef parameter will provide the error result.

    283 | 284 |
    285 |
    289 |
    290 |
    291 | Show on GitHub 292 |
    293 |
    294 |
    295 |
  • 296 |
  • 297 |
    298 | 299 | 300 | 301 | add(domain:account:password:completion:) 302 | 303 |
    304 |
    305 |
    306 |
    307 |
    308 |
    309 |

    Asynchronously store (or update) a shared password for a website.

    310 | 311 |

    This function adds a shared password item which will be accessible by Safari and applications that have the 312 | specified fully-qualified domain name in their com.apple.developer.associated-domains entitlement. If a shared 313 | password item already exists for the specified website and account, it will be updated with the provided 314 | password.

    315 | 316 |
    317 |

    Note

    318 |

    Note:

    319 | 320 |

    Since a request involving shared web credentials may potentially require user interaction or other 321 | verification to be approved, this function is dispatched asynchronously; your code provides a completion 322 | handler that will be called once the results (if any) are available.

    323 | 324 |
    325 | 326 |
    327 |
    328 |

    Declaration

    329 |
    330 |

    Swift

    331 |
    public static func add(domain: String, account: String, password: String, completion: WriteCompletion? = nil)
    332 | 333 |
    334 |
    335 |
    336 |

    Parameters

    337 | 338 | 339 | 340 | 345 | 351 | 352 | 353 | 358 | 364 | 365 | 366 | 371 | 377 | 378 | 379 | 384 | 390 | 391 | 392 |
    341 | 342 | domain 343 | 344 | 346 |
    347 |

    The fully qualified domain name of the website requiring the password.

    348 | 349 |
    350 |
    354 | 355 | account 356 | 357 | 359 |
    360 |

    The account name associated with this password.

    361 | 362 |
    363 |
    367 | 368 | password 369 | 370 | 372 |
    373 |

    The password to be stored.

    374 | 375 |
    376 |
    380 | 381 | completion 382 | 383 | 385 |
    386 |

    A block which will be invoked when the function has completed. If the shared password was successfully added, the CFErrorRef parameter passed to the block will be nil. If the error parameter is non-nil, an error occurred and the error reference will hold the result.

    387 | 388 |
    389 |
    393 |
    394 |
    395 | Show on GitHub 396 |
    397 |
    398 |
    399 |
  • 400 |
  • 401 |
    402 | 403 | 404 | 405 | remove(domain:account:completion:) 406 | 407 |
    408 |
    409 |
    410 |
    411 |
    412 |
    413 |

    Asynchronously remove a shared password for a website.

    414 | 415 |

    This function remove a shared password item which will be accessible by Safari and applications that have the 416 | specified fully-qualified domain name in their com.apple.developer.associated-domains entitlement.

    417 | 418 |
    419 |

    Note

    420 |

    Note:

    421 | 422 |

    Since a request involving shared web credentials may potentially require user interaction or other 423 | verification to be approved, this function is dispatched asynchronously; your code provides a completion 424 | handler that will be called once the results (if any) are available.

    425 | 426 |
    427 | 428 |
    429 |
    430 |

    Declaration

    431 |
    432 |

    Swift

    433 |
    public static func remove(domain: String, account: String, completion: WriteCompletion? = nil)
    434 | 435 |
    436 |
    437 |
    438 |

    Parameters

    439 | 440 | 441 | 442 | 447 | 453 | 454 | 455 | 460 | 466 | 467 | 468 | 473 | 479 | 480 | 481 |
    443 | 444 | domain 445 | 446 | 448 |
    449 |

    The fully qualified domain name of the website requiring the password.

    450 | 451 |
    452 |
    456 | 457 | account 458 | 459 | 461 |
    462 |

    The account name associated with this password.

    463 | 464 |
    465 |
    469 | 470 | completion 471 | 472 | 474 |
    475 |

    A block which will be invoked when the function has completed. If the shared password was successfully removed, the CFErrorRef parameter passed to the block will be nil. If the error parameter is non-nil, an error occurred and the error reference will hold the result.

    476 | 477 |
    478 |
    482 |
    483 |
    484 | Show on GitHub 485 |
    486 |
    487 |
    488 |
  • 489 |
490 |
491 |
492 |
493 | 494 | 495 | 496 |

Generating Passwords

497 |
498 |
499 |
    500 |
  • 501 |
    502 | 503 | 504 | 505 | generatePassword() 506 | 507 |
    508 |
    509 |
    510 |
    511 |
    512 |
    513 |

    Returns a randomly generated password.

    514 | 515 |
    516 |
    517 |

    Declaration

    518 |
    519 |

    Swift

    520 |
    public static func generatePassword() -> String?
    521 | 522 |
    523 |
    524 |
    525 |

    Return Value

    526 |

    Optional String password in the form xxx-xxx-xxx-xxx where x is taken from the sets "abcdefghkmnopqrstuvwxy", "ABCDEFGHJKLMNPQRSTUVWXYZ", "3456789" with at least one character from each set being present or nil if it failed.

    527 | 528 |
    529 |
    530 | Show on GitHub 531 |
    532 |
    533 |
    534 |
  • 535 |
536 |
537 |
538 |
539 | 543 |
544 |
545 | 546 | 547 | 548 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; 143 | white-space: nowrap; } 144 | .nav-group-task a { 145 | color: #888; } 146 | 147 | .main-content { 148 | background-color: #fff; 149 | border: 1px solid #e2e2e2; 150 | margin-left: 246px; 151 | position: absolute; 152 | overflow: hidden; 153 | padding-bottom: 60px; 154 | top: 70px; 155 | width: 734px; } 156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 157 | margin-bottom: 1em; } 158 | .main-content p { 159 | line-height: 1.8em; } 160 | .main-content section .section:first-child { 161 | margin-top: 0; 162 | padding-top: 0; } 163 | .main-content section .task-group-section .task-group:first-of-type { 164 | padding-top: 10px; } 165 | .main-content section .task-group-section .task-group:first-of-type .section-name { 166 | padding-top: 15px; } 167 | 168 | .section { 169 | padding: 0 25px; } 170 | 171 | .highlight { 172 | background-color: #eee; 173 | padding: 10px 12px; 174 | border: 1px solid #e2e2e2; 175 | border-radius: 4px; 176 | overflow-x: auto; } 177 | 178 | .declaration .highlight { 179 | overflow-x: initial; 180 | padding: 0 40px 40px 0; 181 | margin-bottom: -25px; 182 | background-color: transparent; 183 | border: none; } 184 | 185 | .section-name { 186 | margin: 0; 187 | margin-left: 18px; } 188 | 189 | .task-group-section { 190 | padding-left: 6px; 191 | border-top: 1px solid #e2e2e2; } 192 | 193 | .task-group { 194 | padding-top: 0px; } 195 | 196 | .task-name-container a[name]:before { 197 | content: ""; 198 | display: block; 199 | padding-top: 70px; 200 | margin: -70px 0 0; } 201 | 202 | .item { 203 | padding-top: 8px; 204 | width: 100%; 205 | list-style-type: none; } 206 | .item a[name]:before { 207 | content: ""; 208 | display: block; 209 | padding-top: 70px; 210 | margin: -70px 0 0; } 211 | .item code { 212 | background-color: transparent; 213 | padding: 0; } 214 | .item .token { 215 | padding-left: 3px; 216 | margin-left: 15px; 217 | font-size: 11.9px; } 218 | .item .declaration-note { 219 | font-size: .85em; 220 | color: gray; 221 | font-style: italic; } 222 | 223 | .pointer-container { 224 | border-bottom: 1px solid #e2e2e2; 225 | left: -23px; 226 | padding-bottom: 13px; 227 | position: relative; 228 | width: 110%; } 229 | 230 | .pointer { 231 | background: #f9f9f9; 232 | border-left: 1px solid #e2e2e2; 233 | border-top: 1px solid #e2e2e2; 234 | height: 12px; 235 | left: 21px; 236 | top: -7px; 237 | -webkit-transform: rotate(45deg); 238 | -moz-transform: rotate(45deg); 239 | -o-transform: rotate(45deg); 240 | transform: rotate(45deg); 241 | position: absolute; 242 | width: 12px; } 243 | 244 | .height-container { 245 | display: none; 246 | left: -25px; 247 | padding: 0 25px; 248 | position: relative; 249 | width: 100%; 250 | overflow: hidden; } 251 | .height-container .section { 252 | background: #f9f9f9; 253 | border-bottom: 1px solid #e2e2e2; 254 | left: -25px; 255 | position: relative; 256 | width: 100%; 257 | padding-top: 10px; 258 | padding-bottom: 5px; } 259 | 260 | .aside, .language { 261 | padding: 6px 12px; 262 | margin: 12px 0; 263 | border-left: 5px solid #dddddd; 264 | overflow-y: hidden; } 265 | .aside .aside-title, .language .aside-title { 266 | font-size: 9px; 267 | letter-spacing: 2px; 268 | text-transform: uppercase; 269 | padding-bottom: 0; 270 | margin: 0; 271 | color: #aaa; 272 | -webkit-user-select: none; } 273 | .aside p:last-child, .language p:last-child { 274 | margin-bottom: 0; } 275 | 276 | .language { 277 | border-left: 5px solid #cde9f4; } 278 | .language .aside-title { 279 | color: #4b8afb; } 280 | 281 | .aside-warning { 282 | border-left: 5px solid #ff6666; } 283 | .aside-warning .aside-title { 284 | color: #ff0000; } 285 | 286 | .graybox { 287 | border-collapse: collapse; 288 | width: 100%; } 289 | .graybox p { 290 | margin: 0; 291 | word-break: break-word; 292 | min-width: 50px; } 293 | .graybox td { 294 | border: 1px solid #e2e2e2; 295 | padding: 5px 25px 5px 10px; 296 | vertical-align: middle; } 297 | .graybox tr td:first-of-type { 298 | text-align: right; 299 | padding: 7px; 300 | vertical-align: top; 301 | word-break: normal; 302 | width: 40px; } 303 | 304 | .slightly-smaller { 305 | font-size: 0.9em; } 306 | 307 | #footer { 308 | position: absolute; 309 | bottom: 10px; 310 | margin-left: 25px; } 311 | #footer p { 312 | margin: 0; 313 | color: #aaa; 314 | font-size: 0.8em; } 315 | 316 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 317 | display: none; } 318 | html.dash .main-content { 319 | width: 980px; 320 | margin-left: 0; 321 | border: none; 322 | width: 100%; 323 | top: 0; 324 | padding-bottom: 0; } 325 | html.dash .height-container { 326 | display: block; } 327 | html.dash .item .token { 328 | margin-left: 0; } 329 | html.dash .content-wrapper { 330 | width: auto; } 331 | html.dash #footer { 332 | position: static; } 333 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/docsets/.docset/Contents/Resources/Documents/img/carat.png -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/docsets/.docset/Contents/Resources/Documents/img/dash.png -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/docsets/.docset/Contents/Resources/Documents/img/gh.png -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |

View on GitHub

18 |

Install in Dash

19 |
20 |
21 |
22 | 27 |
28 |
29 | 44 |
45 |
46 |
47 | 48 |

SharedWebCredentials

49 | 50 |

Version 51 | Swift Version 52 | Carthage compatible

53 | 54 |

Swift library for easily working with Shared Web Credentials for iOS with Carthage support.

55 | 56 |

Released under the MIT license. Enjoy.

57 |

Installation

58 | 59 |

Carthage is the recommended way to install SharedWebCredentials. Add the following to your Cartfile:

60 |
github "soffes/SharedWebCredentials"
 61 | 
62 |

Prerequisites

63 | 64 |

To use Shared Web Credentials, you’ll need to setup the proper entitlements and an associated domain. Here’s documentation on how to do that.

65 | 66 |

Be sure you don’t miss:

67 | 68 |
69 |

If your app runs in iOS 9 and later and you use HTTPS to serve the file, you can create a plain text file that uses the application/json MIME type and you don’t need to sign it.

70 |
71 | 72 |

All of that signing stuff is a real pain. If you are targeting iOS 9 or later, you can skip this step!

73 | 74 |

Once you get all of that stuff setup, you can use this framework instead of the Security framework to access the credentials in a Swift-friendly way.

75 |

Usage

76 | 77 |

Start by importing the framework:

78 |
import SharedWebCredentials
 79 | 
80 |

Retrieve Credentials

81 | 82 |

The system will show its own UI for letting the user choose which account they want to use to sign into the app. The result will be a Credential struct or nil.

83 |
Store.get { credential, error in
 84 |     if let credential = credential {
 85 |         print("Username: \(credential.account), Password: \(credential.password)")
 86 |     }
 87 | 
 88 |     print("Error: \(error)")
 89 | }
 90 | 
91 | 92 |

It will automatically use any of the domains you have set in your com.apple.developer.associated-domains entitlement. You can optionally specify the domain argument to pick a specific one.

93 |

Adding a New Credential

94 |
Store.add(domain: "myapp.com", account: "steve", password: "password")
 95 | 
96 |

Removing a Credential

97 |
Store.remove(domain: "myapp.com", account: "steve")
 98 | 
99 | 100 |
101 |
102 | 106 |
107 |
108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | 42 | // Dumb down quotes within code blocks that delimit strings instead of quotations 43 | // https://github.com/realm/jazzy/issues/714 44 | $("code q").replaceWith(function () { 45 | return ["\"", $(this).contents(), "\""]; 46 | }); 47 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/search.json: -------------------------------------------------------------------------------- 1 | {"Structs/Store.html#/s:V20SharedWebCredentials5Store14ReadCompletion":{"name":"ReadCompletion","abstract":"

Completion block for reading from shared web credentials.

","parent_name":"Store"},"Structs/Store.html#/s:V20SharedWebCredentials5Store15WriteCompletion":{"name":"WriteCompletion","abstract":"

Completion block for writing to shared web credentials.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store3getFT6domainGSqSS_7accountGSqSS_10completionFTGSqVS_10Credential_GSqCSo7CFError__T__T_":{"name":"get(domain:account:completion:)","abstract":"

Asynchronously obtain one or more shared passwords for a website.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store3addFT6domainSS7accountSS8passwordSS10completionGSqFGSqCSo7CFError_T___T_":{"name":"add(domain:account:password:completion:)","abstract":"

Asynchronously store (or update) a shared password for a website.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store6removeFT6domainSS7accountSS10completionGSqFGSqCSo7CFError_T___T_":{"name":"remove(domain:account:completion:)","abstract":"

Asynchronously remove a shared password for a website.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store16generatePasswordFT_GSqSS_":{"name":"generatePassword()","abstract":"

Returns a randomly generated password.

","parent_name":"Store"},"Structs/Credential.html#/s:vV20SharedWebCredentials10Credential6domainSS":{"name":"domain","abstract":"

Fully qualified domain name of the website

","parent_name":"Credential"},"Structs/Credential.html#/s:vV20SharedWebCredentials10Credential7accountSS":{"name":"account","abstract":"

Account name

","parent_name":"Credential"},"Structs/Credential.html#/s:vV20SharedWebCredentials10Credential8passwordSS":{"name":"password","abstract":"

Password

","parent_name":"Credential"},"Structs/Credential.html":{"name":"Credential","abstract":"

Single credential from Shared Web Credentials Store.

"},"Structs/Store.html":{"name":"Store","abstract":"

Shared Web Credentials Store.

"},"Structs.html":{"name":"Structs","abstract":"The following structs are available globally."}} -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/undocumented.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": [ 3 | 4 | ], 5 | "source_directory": "/Users/soffes/Code/soffes/SharedWebCredentials" 6 | } -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/docSet.dsidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/docsets/.docset/Contents/Resources/docSet.dsidx -------------------------------------------------------------------------------- /docs/docsets/.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/docsets/.tgz -------------------------------------------------------------------------------- /docs/docsets/.xml: -------------------------------------------------------------------------------- 1 | 1.0https://soffes.github.io/SharedWebCredentials/docsets/.tgz 2 | -------------------------------------------------------------------------------- /docs/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/img/carat.png -------------------------------------------------------------------------------- /docs/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/img/dash.png -------------------------------------------------------------------------------- /docs/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SharedWebCredentials/26342d959a0c7a6fd8697af590f7bcf5b6add1b7/docs/img/gh.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |

View on GitHub

18 |

Install in Dash

19 |
20 |
21 |
22 | 27 |
28 |
29 | 44 |
45 |
46 |
47 | 48 |

SharedWebCredentials

49 | 50 |

Version 51 | Swift Version 52 | Carthage compatible

53 | 54 |

Swift library for easily working with Shared Web Credentials for iOS with Carthage support.

55 | 56 |

Released under the MIT license. Enjoy.

57 |

Installation

58 | 59 |

Carthage is the recommended way to install SharedWebCredentials. Add the following to your Cartfile:

60 |
github "soffes/SharedWebCredentials"
 61 | 
62 |

Prerequisites

63 | 64 |

To use Shared Web Credentials, you’ll need to setup the proper entitlements and an associated domain. Here’s documentation on how to do that.

65 | 66 |

Be sure you don’t miss:

67 | 68 |
69 |

If your app runs in iOS 9 and later and you use HTTPS to serve the file, you can create a plain text file that uses the application/json MIME type and you don’t need to sign it.

70 |
71 | 72 |

All of that signing stuff is a real pain. If you are targeting iOS 9 or later, you can skip this step!

73 | 74 |

Once you get all of that stuff setup, you can use this framework instead of the Security framework to access the credentials in a Swift-friendly way.

75 |

Usage

76 | 77 |

Start by importing the framework:

78 |
import SharedWebCredentials
 79 | 
80 |

Retrieve Credentials

81 | 82 |

The system will show its own UI for letting the user choose which account they want to use to sign into the app. The result will be a Credential struct or nil.

83 |
Store.get { credential, error in
 84 |     if let credential = credential {
 85 |         print("Username: \(credential.account), Password: \(credential.password)")
 86 |     }
 87 | 
 88 |     print("Error: \(error)")
 89 | }
 90 | 
91 | 92 |

It will automatically use any of the domains you have set in your com.apple.developer.associated-domains entitlement. You can optionally specify the domain argument to pick a specific one.

93 |

Adding a New Credential

94 |
Store.add(domain: "myapp.com", account: "steve", password: "password")
 95 | 
96 |

Removing a Credential

97 |
Store.remove(domain: "myapp.com", account: "steve")
 98 | 
99 | 100 |
101 |
102 | 106 |
107 |
108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /docs/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | 42 | // Dumb down quotes within code blocks that delimit strings instead of quotations 43 | // https://github.com/realm/jazzy/issues/714 44 | $("code q").replaceWith(function () { 45 | return ["\"", $(this).contents(), "\""]; 46 | }); 47 | -------------------------------------------------------------------------------- /docs/search.json: -------------------------------------------------------------------------------- 1 | {"Structs/Store.html#/s:V20SharedWebCredentials5Store14ReadCompletion":{"name":"ReadCompletion","abstract":"

Completion block for reading from shared web credentials.

","parent_name":"Store"},"Structs/Store.html#/s:V20SharedWebCredentials5Store15WriteCompletion":{"name":"WriteCompletion","abstract":"

Completion block for writing to shared web credentials.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store3getFT6domainGSqSS_7accountGSqSS_10completionFTGSqVS_10Credential_GSqCSo7CFError__T__T_":{"name":"get(domain:account:completion:)","abstract":"

Asynchronously obtain one or more shared passwords for a website.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store3addFT6domainSS7accountSS8passwordSS10completionGSqFGSqCSo7CFError_T___T_":{"name":"add(domain:account:password:completion:)","abstract":"

Asynchronously store (or update) a shared password for a website.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store6removeFT6domainSS7accountSS10completionGSqFGSqCSo7CFError_T___T_":{"name":"remove(domain:account:completion:)","abstract":"

Asynchronously remove a shared password for a website.

","parent_name":"Store"},"Structs/Store.html#/s:ZFV20SharedWebCredentials5Store16generatePasswordFT_GSqSS_":{"name":"generatePassword()","abstract":"

Returns a randomly generated password.

","parent_name":"Store"},"Structs/Credential.html#/s:vV20SharedWebCredentials10Credential6domainSS":{"name":"domain","abstract":"

Fully qualified domain name of the website

","parent_name":"Credential"},"Structs/Credential.html#/s:vV20SharedWebCredentials10Credential7accountSS":{"name":"account","abstract":"

Account name

","parent_name":"Credential"},"Structs/Credential.html#/s:vV20SharedWebCredentials10Credential8passwordSS":{"name":"password","abstract":"

Password

","parent_name":"Credential"},"Structs/Credential.html":{"name":"Credential","abstract":"

Single credential from Shared Web Credentials Store.

"},"Structs/Store.html":{"name":"Store","abstract":"

Shared Web Credentials Store.

"},"Structs.html":{"name":"Structs","abstract":"The following structs are available globally."}} -------------------------------------------------------------------------------- /docs/undocumented.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": [ 3 | 4 | ], 5 | "source_directory": "/Users/soffes/Code/soffes/SharedWebCredentials" 6 | } --------------------------------------------------------------------------------