def get_backup_auth_from_node(self, base_url, auth_token, hive_did): rt, status_code, err = self.post(base_url + '/api/v1/did/backup_auth', {"jwt": auth_token}) if err != None: return None, "Post backup_auth error: " + err token = rt["backup_token"] if token is None: return None, "Token is none." jws = lib.DefaultJWSParser_Parse(token.encode()) if not jws: return None, "Backup token DefaultJWSParser_Parse error: " + ffi.string( lib.DIDError_GetLastErrorMessage()).decode() aud = ffi.string(lib.JWT_GetAudience(jws)).decode() if aud != self.get_did_string(): lib.JWT_Destroy(jws) return None, "Audience is error." issuer = ffi.string(lib.JWT_GetIssuer(jws)).decode() lib.JWT_Destroy(jws) if issuer is None: return None, "Issuer is none." if issuer != hive_did: return None, "Issuer is error." return token, None
def sign_in(self): body = request.get_json(force=True, silent=True) if body is None: return self.response.response_err(UNAUTHORIZED, "parameter is not application/json") document = body.get('document', None) if document is None: return self.response.response_err(BAD_REQUEST, "Thd did document is null") doc_str = json.dumps(body.get('document', None)) doc = lib.DIDDocument_FromJson(doc_str.encode()) if (not doc) or (not lib.DIDDocument_IsValid(doc)): return self.response.response_err(BAD_REQUEST, "Thd did document is vaild") did = lib.DIDDocument_GetSubject(doc) if not did: return self.response.response_err(BAD_REQUEST, "Thd did document is vaild, can't get did.") spec_did_str = ffi.string(lib.DID_GetMethodSpecificId(did)).decode() f = open(hive_setting.DID_DATA_LOCAL_DIDS+ os.sep + spec_did_str, "w") try: f.write(doc_str) finally: f.close() did_str = "did:" + ffi.string(lib.DID_GetMethod(did)).decode() + ":" + spec_did_str # save to db nonce = create_nonce() exp = int(datetime.now().timestamp()) + hive_setting.AUTH_CHALLENGE_EXPIRED if not self.__save_nonce_to_db(nonce, did_str, exp): return self.response.response_err(INTERNAL_SERVER_ERROR, "save to db fail!") # response token builder = lib.DIDDocument_GetJwtBuilder(self.doc) if not builder: return self.response.response_err(INTERNAL_SERVER_ERROR, "Can't get jwt builder.") lib.JWTBuilder_SetHeader(builder, "type".encode(), "JWT".encode()) lib.JWTBuilder_SetHeader(builder, "version".encode(), "1.0".encode()) lib.JWTBuilder_SetSubject(builder, "DIDAuthChallenge".encode()) lib.JWTBuilder_SetAudience(builder, did_str.encode()) lib.JWTBuilder_SetClaim(builder, "nonce".encode(), nonce.encode()) lib.JWTBuilder_SetExpiration(builder, exp) lib.JWTBuilder_Sign(builder, ffi.NULL, self.storepass) token = lib.JWTBuilder_Compact(builder) if not token: return self.response.response_err(INTERNAL_SERVER_ERROR, "Compact builder to a token is fail.") token = ffi.string(token).decode() # print(token) lib.JWTBuilder_Destroy(builder) data = { "challenge": token, } return self.response.response_ok(data)
def get_did_string_from_did(self, did): if not did: return None method = lib.DID_GetMethod(did) if not method: return None method = ffi.string(method).decode() sep_did = lib.DID_GetMethodSpecificId(did) if not sep_did: return None sep_did = ffi.string(sep_did).decode() return "did:" + method + ":" + sep_did
def get_info_from_token(self, token): if token is None: return None, "Then token is none!" token_splits = token.split(".") if token_splits is None: return None, "Then token is invalid!" if (len(token_splits) != 3) or token_splits[2] == "": return None, "Then token is invalid!" jws = lib.DefaultJWSParser_Parse(token.encode()) if not jws: return None, self.get_error_message("JWS parser") issuer = lib.JWT_GetIssuer(jws) if not issuer: lib.JWT_Destroy(jws) return None, self.get_error_message("JWT getIssuer") issuer = ffi.string(issuer).decode() if issuer != self.get_did_string(): lib.JWT_Destroy(jws) return None, "Then issuer is invalid!" expired = lib.JWT_GetExpiration(jws) now = (int)(datetime.now().timestamp()) if now > expired: lib.JWT_Destroy(jws) return None, "Then token is expired!" props = lib.JWT_GetClaim(jws, "props".encode()) if not props: lib.JWT_Destroy(jws) return None, "Then props is none!" props_str = ffi.string(props).decode() props_json = json.loads(props_str) app_instance_did = ffi.string(lib.JWT_GetAudience(jws)).decode() if not app_instance_did: lib.JWT_Destroy(jws) return None, "Then app instance id is none!" props_json[APP_INSTANCE_DID] = app_instance_did lib.JWT_Destroy(jws) # print(props_json) return props_json, None
def get_auth_token_by_sign_in(self, base_url, vc_str, subject): vc = lib.Credential_FromJson(vc_str.encode(), ffi.NULL) if not vc: return None, None, "The credential string is error, unable to rebuild to a credential object." #sign_in doc = lib.DIDStore_LoadDID(self.store, self.did) doc_str = ffi.string(lib.DIDDocument_ToJson(doc, True)).decode() doc = json.loads(doc_str) rt, status_code, err = self.post(base_url + '/api/v1/did/sign_in', {"document": doc}) if err != None: return None, None, "Post sign_in error: " + err jwt = rt["challenge"] if jwt is None: return None, None, "Challenge is none." # print(jwt) jws = lib.DefaultJWSParser_Parse(jwt.encode()) if not jws: return None, None, "Challenge DefaultJWSParser_Parse error: " + ffi.string( lib.DIDError_GetLastErrorMessage()).decode() aud = ffi.string(lib.JWT_GetAudience(jws)).decode() if aud != self.get_did_string(): lib.JWT_Destroy(jws) return None, None, "Audience is error." nonce = ffi.string(lib.JWT_GetClaim(jws, "nonce".encode())).decode() if nonce is None: lib.JWT_Destroy(jws) return None, None, "Nonce is none." hive_did = ffi.string(lib.JWT_GetIssuer(jws)).decode() lib.JWT_Destroy(jws) if hive_did is None: return None, None, "Issuer is none." #auth_token vp_json = self.create_presentation(vc, nonce, hive_did) if vp_json is None: return None, None, "create_presentation error." auth_token = self.create_vp_token(vp_json, subject, hive_did, hive_setting.AUTH_CHALLENGE_EXPIRED) if auth_token is None: return None, None, "create_vp_token error." return auth_token, hive_did, None
def did_auth(self, host, user_did, app_did): # sign_in doc = lib.DIDStore_LoadDID(app_did.store, app_did.did) doc_str = ffi.string(lib.DIDDocument_ToJson(doc, True)).decode() logging.getLogger("test_auth_common").debug(f"\ndoc_str: {doc_str}") doc = json.loads(doc_str) param = {"document": doc} r = requests.post(host + '/api/v1/did/sign_in', json=param, headers=self.json_header()) self.assert200(r.status_code) rt = r.json() jwt = rt["challenge"] # print(jwt) jws = lib.DefaultJWSParser_Parse(jwt.encode()) # if not jws: # print(ffi.string(lib.DIDError_GetLastErrorMessage()).decode()) aud = ffi.string(lib.JWT_GetAudience(jws)).decode() self.assertEqual(aud, app_did.get_did_string()) nonce = ffi.string(lib.JWT_GetClaim(jws, "nonce".encode())).decode() hive_did = ffi.string(lib.JWT_GetIssuer(jws)).decode() lib.JWT_Destroy(jws) # auth vc = user_did.issue_auth(app_did) vp_json = app_did.create_presentation(vc, nonce, hive_did) auth_token = app_did.create_vp_token(vp_json, "DIDAuthResponse", hive_did, 60) # print(auth_token) logging.getLogger("test_auth_common").debug( f"\nauth_token: {auth_token}") param = { "jwt": auth_token, } r = requests.post(host + '/api/v1/did/auth', json=param, headers=self.json_header()) self.assert200(r.status_code) rt = r.json() token = rt["access_token"] jws = lib.DefaultJWSParser_Parse(token.encode()) aud = ffi.string(lib.JWT_GetAudience(jws)).decode() self.assertEqual(aud, app_did.get_did_string()) issuer = ffi.string(lib.JWT_GetIssuer(jws)).decode() lib.JWT_Destroy(jws) # print(token) logging.getLogger("test_auth_common").debug(f"\ntoken: {token}") app_did.set_access_token(token) # auth_check # token = test_common.get_auth_token() r = requests.post(host + '/api/v1/did/check_token', json=param, headers=self.auth_header(token)) self.assert200(r.status_code) return token, hive_did
def MyDIDLocalResovleHandle(did): spec_did_str = ffi.string(lib.DID_GetMethodSpecificId(did)).decode() doc = ffi.NULL file_path = hive_setting.DID_DATA_LOCAL_DIDS + os.sep + spec_did_str is_exist = os.path.exists(file_path) if is_exist: f = open(file_path, "r") try: doc_str = f.read() doc = lib.DIDDocument_FromJson(doc_str.encode()) finally: f.close() return doc
def create_presentation(self, vc, nonce, realm): vpid = lib.DIDURL_NewByDid(self.did, "jwtvp".encode()) type0 = ffi.new("char[]", "VerifiablePresentation".encode()) types = ffi.new("char **", type0) vp = lib.Presentation_Create(vpid, self.did, types, 1, nonce.encode(), realm.encode(), ffi.NULL, self.store, self.storepass, 1, vc) lib.DIDURL_Destroy(vpid) # print_err() vp_json = ffi.string(lib.Presentation_ToJson(vp, True)).decode() # print(vp_json) logging.debug(f"vp_json: {vp_json}") return vp_json
def __create_token(self, auth_info, subject): if not isinstance(auth_info, dict): return None, "auth info isn't dict type" doc = lib.DIDStore_LoadDID(self.store, self.did) if not doc: return None, self.get_error_message("The doc load from did") builder = lib.DIDDocument_GetJwtBuilder(doc) if not builder: return None, "Can't get jwt builder." lib.JWTBuilder_SetHeader(builder, "typ".encode(), "JWT".encode()) lib.JWTBuilder_SetHeader(builder, "version".encode(), "1.0".encode()) lib.JWTBuilder_SetSubject(builder, subject.encode()) lib.JWTBuilder_SetAudience(builder, auth_info["id"].encode()) lib.JWTBuilder_SetExpiration(builder, auth_info["expTime"]) props = {} for key in auth_info: if key != "expTime" and key != "id": props[key] = auth_info[key] props_str = json.dumps(props) ret = lib.JWTBuilder_SetClaim(builder, "props".encode(), props_str.encode()) if not ret: return None, self.get_error_message( "JWTBuilder_SetClaim 'props' to a token") lib.JWTBuilder_Sign(builder, ffi.NULL, self.storepass) token = lib.JWTBuilder_Compact(builder) if not token: return None, self.get_error_message("Compact builder to a token") token = ffi.string(token).decode() lib.JWTBuilder_Destroy(builder) return token, None
def test_4_inter_put_file(self): self.init_vault_service(self.host1, self.token1) self.init_backup_service(self.host2, self.token2) vc = self.user_did.issue_backup_auth(self.hive_did1, self.host2, self.hive_did2) vc_json = ffi.string(lib.Credential_ToString(vc, True)).decode() content = {"backup_credential": vc_json} host, backup_token, err = view.h_auth.backup_auth_request(content) self.assertIsNone(err) input_text = "this is a test put file" file_name = "test_put_file.txt" temp = BytesIO() temp.write(input_text.encode(encoding="utf-8")) temp.seek(0) temp.name = 'temp.txt' url = self.host2 + INTER_BACKUP_FILE_URL + '?file=' + file_name r = requests.put(url, data=temp, headers={"Authorization": "token " + backup_token}) self.assert200(r.status_code) r = requests.get(host + INTER_BACKUP_FILE_URL + "?file=" + file_name, stream=True, headers={"Authorization": "token " + backup_token}) self.assertEquals(r.text, input_text) r = requests.delete(host + INTER_BACKUP_FILE_URL + "?file=" + file_name, headers={"Authorization": "token " + backup_token}) self.assert200(r.status_code) r = requests.get(host + INTER_BACKUP_FILE_URL + "?file=" + file_name, stream=True, headers={"Authorization": "token " + backup_token}) self.assertEquals(r.status_code, NOT_FOUND)
def test_1_save_restore_hive_node(self): self.init_vault_service(self.host1, self.token1) self.add_vault_data(self.host1, self.token1) self.check_vault_data(self.host1, self.token1) self.init_backup_service(self.host2, self.token2) vc = self.user_did.issue_backup_auth(self.hive_did1, self.host2, self.hive_did2) vc_json = ffi.string(lib.Credential_ToString(vc, True)).decode() self.save_to_backup(self.host1, self.token1, vc_json) self.clean_vault_data(self.host1, self.token1) self.restore_from_backup(self.host1, self.token1, vc_json) time.sleep(2) self.check_vault_data(self.host1, self.token1) # active test self.init_vault_service(self.host2, self.token2) self.active_backup_vault(self.host2, self.token2) self.check_vault_data(self.host2, self.token2)
def create_vp_token(self, vp_json, subject, hive_did, expire): doc = lib.DIDStore_LoadDID(self.store, self.did) builder = lib.DIDDocument_GetJwtBuilder(doc) ticks = int(datetime.now().timestamp()) iat = ticks nbf = ticks exp = ticks + expire lib.JWTBuilder_SetHeader(builder, "type".encode(), "JWT".encode()) lib.JWTBuilder_SetHeader(builder, "version".encode(), "1.0".encode()) lib.JWTBuilder_SetSubject(builder, subject.encode()) lib.JWTBuilder_SetAudience(builder, hive_did.encode()) lib.JWTBuilder_SetIssuedAt(builder, iat) lib.JWTBuilder_SetExpiration(builder, exp) lib.JWTBuilder_SetNotBefore(builder, nbf) lib.JWTBuilder_SetClaimWithJson(builder, "presentation".encode(), vp_json.encode()) lib.JWTBuilder_Sign(builder, ffi.NULL, self.storepass) token = ffi.string(lib.JWTBuilder_Compact(builder)).decode() lib.JWTBuilder_Destroy(builder) # print(token) return token
def get_error_message(): return str(ffi.string(lib.DIDError_GetLastErrorMessage()), encoding='utf-8')
def __get_auth_token_info(self, props): # get jwt body = request.get_json(force=True, silent=True) if body is None: return None, "The parameter is not application/json" jwt = body.get('jwt', None) if jwt is None: return None, "The jwt is none." # check jwt token jws = lib.DefaultJWSParser_Parse(jwt.encode()) if not jws: return None, self.get_error_message("JWS parser") vp_str = lib.JWT_GetClaimAsJson(jws, "presentation".encode()) if not vp_str: lib.JWT_Destroy(jws) return None, "The jwt's presentation is none." vp = lib.Presentation_FromJson(vp_str) if not vp: lib.JWT_Destroy(jws) return None, "The presentation string is error, unable to rebuild to a presentation object." vp_json = json.loads(ffi.string(vp_str).decode()) lib.JWT_Destroy(jws) # check vp if lib.Presentation_IsValid(vp) != 1: return None, self.get_error_message("Presentation isValid") # print(ffi.string(vp_str).decode()) # check nonce nonce = lib.Presentation_GetNonce(vp) if not nonce: return None, "The nonce is none." nonce = ffi.string(nonce).decode() if nonce is None: return None, "The nonce is isn't valid." # check did:nonce from db info = get_did_info_by_nonce(nonce) if info is None: return None, "The nonce is error." # check realm realm = lib.Presentation_GetRealm(vp) if not realm: return None, "The realm is none." realm = ffi.string(realm).decode() if realm is None: return None, "The realm is isn't valid." if realm != self.get_did_string(): return None, "The realm is error." # check vc count = lib.Presentation_GetCredentialCount(vp) if count < 1: return None, "The credential count is error." if not "verifiableCredential" in vp_json: return None, "The credential isn't exist." vcs_json = vp_json["verifiableCredential"] if not isinstance(vcs_json, list): return None, "The verifiableCredential isn't valid" vc_json = vcs_json[0] if vc_json is None: return None, "The credential isn't exist" vc_str = json.dumps(vc_json) credential_info, err = self.get_credential_info(vc_str, props) if not credential_info is None: if credential_info["id"] != info[APP_INSTANCE_DID]: return None, "The app instance did is error." credential_info["nonce"] = nonce if info[DID_INFO_NONCE_EXPIRED] < int(datetime.now().timestamp()): return None, "The nonce is expired" return credential_info, err
def test_auth_common(self, user_did, app_did): # sign_in doc = lib.DIDStore_LoadDID(app_did.store, app_did.did) doc_str = ffi.string(lib.DIDDocument_ToJson(doc, True)).decode() logging.getLogger("test_auth_common").debug(f"\ndoc_str: {doc_str}") doc = json.loads(doc_str) rt, s = self.parse_response( self.test_client.post('/api/v1/did/sign_in', data=json.dumps({ "document": doc, }), headers=self.json_header)) self.assert200(s) self.assertEqual(rt["_status"], "OK") jwt = rt["challenge"] # print(jwt) jws = lib.DefaultJWSParser_Parse(jwt.encode()) # if not jws: # print(ffi.string(lib.DIDError_GetMessage()).decode()) aud = ffi.string(lib.JWT_GetAudience(jws)).decode() self.assertEqual(aud, app_did.get_did_string()) nonce = ffi.string(lib.JWT_GetClaim(jws, "nonce".encode())).decode() hive_did = ffi.string(lib.JWT_GetIssuer(jws)).decode() lib.JWT_Destroy(jws) # auth vc = user_did.issue_auth(app_did) vp_json = app_did.create_presentation(vc, nonce, hive_did) auth_token = app_did.create_vp_token(vp_json, "DIDAuthResponse", hive_did, 60) # print(auth_token) logging.getLogger("test_auth_common").debug(f"\nauth_token: {auth_token}") rt, s = self.parse_response( self.test_client.post('/api/v1/did/auth', data=json.dumps({ "jwt": auth_token, }), headers=self.json_header)) self.assert200(s) self.assertEqual(rt["_status"], "OK") token = rt["access_token"] jws = lib.DefaultJWSParser_Parse(token.encode()) aud = ffi.string(lib.JWT_GetAudience(jws)).decode() self.assertEqual(aud, app_did.get_did_string()) issuer = ffi.string(lib.JWT_GetIssuer(jws)).decode() lib.JWT_Destroy(jws) # print(token) logging.getLogger("test_auth_common").debug(f"\ntoken: {token}") app_did.set_access_token(token) # auth_check # token = test_common.get_auth_token() self.json_header = [ ("Authorization", "token " + token), self.content_type, ] rt, s = self.parse_response( self.test_client.post('/api/v1/did/check_token', headers=self.json_header)) self.assert200(s) self.assertEqual(rt["_status"], "OK") return token, hive_did
def get_error_message(self, prompt): err_message = ffi.string(lib.DIDError_GetLastErrorMessage()).decode() if not prompt is None: err_message = prompt + " error: " + err_message return err_message